Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

cli: manual recovery `node postinstall.mjs` fails on Windows - `npm_execpath` unset causes silent `spawnSync("npm")` ENOENT

Open Beginner friendly
#56,380 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@soybeanmilka is already working on this.

Since Oct 17, 2026.

  • #56441 by @soybeanmilka — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
73/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
node.js, typescript
Domain
build-system, cli

Research direction

Start with packages/cli/postinstall.mjs, especially the npm executable selection and installPackage() handling described in the report. Reproduce by running node postinstall.mjs outside an npm lifecycle on Windows and inspect the spawn result. Done means manual recovery can invoke npm successfully and failures expose the underlying error.

Written by the indexing model from the issue text.

Description

Summary

The manual recovery step recommended in #55888 - running node postinstall.mjs inside the installed @opencode/cli package - cannot work on Windows when invoked outside an npm lifecycle context.

postinstall.mjs only resolves the npm CLI correctly when npm_execpath is set. Otherwise it falls back to spawnSync("npm", ...), which always fails with ENOENT on Windows because the npm shim is npm.cmd.

The failure is silent: installPackage() treats a non-zero status as a failed install and continues, so the user only ever sees the generic Failed to install OpenCode. Try manually installing ... message, with no npm output and no hint of the real cause.

Environment

  • opencode version: 2.0.31
  • OS: Windows 11 (win32 x64)
  • Node: v24.18.0
  • npm: 11.16.0
  • Install method: global npm install (npm i -g @opencode/cli)
  • npm_execpath: unset (because postinstall.mjs was run directly with node)

Root cause

packages/cli/postinstall.mjs:

// Windows cannot spawn npm's .cmd shim directly, so reuse the npm CLI that runs this script.
const npm = process.env.npm_execpath?.endsWith("npm-cli.js")
  ? [process.execPath, process.env.npm_execpath]
  : ["npm"]

The comment states the intent, but the ["npm"] fallback is unreachable on Windows. childProcess.spawnSync("npm", ...) without shell: true does not resolve .cmd shims through PATHEXT.

Reproduction

PS> cd $env:APPDATA\npm\node_modules\@opencode\cli
PS> node postinstall.mjs
Failed to install OpenCode. Try manually installing "@opencode/cli-windows-x64" or "@opencode/cli-windows-x64-baseline".
# exit code 1, ~0.4s, no npm output

Evidence

Same machine, same session:

npm_execpath                      = undefined
spawnSync("npm",     ...) -> status = null  error = ENOENT
spawnSync("npm.cmd", ...) -> status = null  error = EINVAL
spawnSync(process.execPath, [npmCliJs, "--version"]) -> status = 0  stdout = "11.16.0"

Setting npm_execpath makes the identical invocation succeed:

PS> $env:npm_execpath = "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js"
PS> node postinstall.mjs
# exit code 0

Suggested fix

Resolve the npm CLI robustly instead of assuming it is directly spawnable:

  • resolve npm-cli.js relative to process.execPath (../node_modules/npm/bin/npm-cli.js), or
  • fall back to npm.cmd with shell: true, or
  • resolve through PATHEXT

Separately, consider surfacing result.error when installPackage fails - the current message hides ENOENT entirely, which makes this hard to diagnose.

Additional context

This machine was in the state described by #55888 (bin/opencode.exe left as the 229-byte placeholder). Because node postinstall.mjs was the suggested recovery and it fails on Windows, the install could not be repaired without manually setting npm_execpath.

Related

  • #55888 (closed) - recommends node postinstall.mjs as manual recovery
  • #51553 (open) - npm 12 upgrade leaves the Windows executable stub
Dominant language
TypeScript
Stars
215k
Forks
28.9k
Avg merge
8h 29m
Merged PRs (30d)
252

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from anomalyco/opencode

All issues in anomalyco/opencode

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.