Missing ~/.local/share/opencode/bin directory causes misleading ENOENT errors #1259

Closed
opened 2026-02-16 17:30:11 -05:00 by yindo · 3 comments
Owner

Originally created by @florath on GitHub (Aug 12, 2025).

Summary

OpenCode fails with misleading ENOENT: no such file or directory, posix_spawn errors when performing operations that require subagents (like Write tool tasks). The root cause is that the ~/.local/share/opencode/bin directory
is extensively used throughout the codebase but is never created during initialization.

Environment

  • OS: Linux (Debian 12)
  • OpenCode Version: 0.4.26 (npm installation)
  • Installation Method: npm install -g opencode-ai
  • nvm: upstream installation (not Debian)
  • Node.js: v20.19.4 (via nvm)

Steps to Reproduce

  1. Install nvm from upstream
  2. Install opencode via npm: npm install -g opencode-ai
  3. Start opencode in any directory: opencode
  4. Try to perform any operation that requires the Write tool or subagent spawning
  5. Example: Ask opencode to create a Python file like "Write tictactoe.py"

Expected Behavior

The operation should complete successfully, creating the requested file.

Actual Behavior

The operation fails with a misleading error:

┃  Write tictactoe.py                                                                                                                                                            ┃
┃                                                                                                                                                                                ┃
┃  Error: ENOENT: no such file or directory, posix_spawn '/home/florath/.nvm/versions/node/v20.19.4/lib/node_modules/opencode-ai/node_modules/opencode-linux-x64/bin/opencode' ┃

Debug Information

strace Analysis

Using strace -f opencode reveals the actual issue:

[pid 253474] chdir("/home/florath/.local/share/opencode/bin") = -1 ENOENT (No such file or directory)
[pid 253474] exit_group(127)            = ?
[pid 253474] +++ exited with 127 +++
[pid 253445] <... futex resumed>)       = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
[pid 253444] <... vfork resumed>)       = 253474
[pid 253445] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=253474, si_uid=1000, si_status=127, si_utime=0, si_stime=0} ---
[pid 253444] write(14, "ERROR 2025-08-12T08:02:39 +16ms service=default e=ENOENT: no such file or directory, posix_spawn '/home/florath/.nvm/versions/node/v20.19.4/lib/node_modules/opencode-ai/node_modules/opencode-linux-x64/bin/
opencode' rejection\n", 225) = 225

Key insight: The error is NOT that the opencode binary doesn't exist, but that the process fails to chdir to /home/florath/.local/share/opencode/bin because that directory doesn't exist.

Workaround Confirmation

Creating the directory manually resolves the issue:

mkdir -p ~/.local/share/opencode/bin

After creating this directory, all operations work correctly.

Root Cause Analysis

Directory Definition

In packages/opencode/src/global/index.ts, the bin directory is defined but never created:

export namespace Global {
  export const Path = {
    data,
    bin: path.join(data, "bin"),  // ← Defined here
    log: path.join(data, "log"),
    cache,
    config,
    state,
  } as const
}

await Promise.all([
  fs.mkdir(Global.Path.data, { recursive: true }),
  fs.mkdir(Global.Path.config, { recursive: true }),
  fs.mkdir(Global.Path.state, { recursive: true }),
  fs.mkdir(Global.Path.log, { recursive: true }),
  // ← Global.Path.bin is NOT created here!
])

Extensive Usage Without Creation

The Global.Path.bin directory is used extensively throughout the codebase:

LSP Servers (packages/opencode/src/lsp/server.ts):

// ESLint server installation
const serverPath = path.join(Global.Path.bin, "vscode-eslint", "server", "out", "eslintServer.js")
await $`unzip -o -q ${zipPath}`.cwd(Global.Path.bin).nothrow()

// Go LSP server
env: { ...process.env, GOBIN: Global.Path.bin }
bin = path.join(Global.Path.bin, "gopls" + (process.platform === "win32" ? ".exe" : ""))

// Ruby LSP server  
cmd: ["gem", "install", "ruby-lsp", "--bindir", Global.Path.bin]

// And many more...

Tools (packages/opencode/src/file/fzf.ts, packages/opencode/src/file/ripgrep.ts):

// fzf installation
Global.Path.bin,
const archivePath = path.join(Global.Path.bin, filename)
cwd: Global.Path.bin,

// ripgrep installation
filepath = path.join(Global.Path.bin, "rg" + (process.platform === "win32" ? ".exe" : ""))
cwd: Global.Path.bin,

All of these operations assume the directory exists, but it's never created.

Impact

This bug affects:

  • ✗ Write tool operations that spawn subagents
  • ✗ LSP server installations (ESLint, gopls, ruby-lsp, pyright, etc.)
  • ✗ Tool downloads (fzf, ripgrep)
  • ✗ Any operation that uses Global.Path.bin as working directory
  • ✗ Task tool operations that require process spawning

Proposed Fix

Add the missing directory creation in packages/opencode/src/global/index.ts:

await Promise.all([
  fs.mkdir(Global.Path.data, { recursive: true }),
  fs.mkdir(Global.Path.bin, { recursive: true }),    // ← ADD THIS LINE
  fs.mkdir(Global.Path.config, { recursive: true }),
  fs.mkdir(Global.Path.state, { recursive: true }),
  fs.mkdir(Global.Path.log, { recursive: true }),
])

Additional Notes

  • The error message is misleading because it suggests the opencode binary is missing, when actually it's a working directory issue
  • Setting OPENCODE_BIN_PATH environment variable does not help because the issue occurs before any subprocess spawning
  • This appears to be a long-standing oversight where the directory was defined and used but never actually created during initialization - which might highly depend on the used installation method.

Verification

After applying the fix, users should be able to:

  1. Perform Write tool operations without errors
  2. Use LSP features that require server installation
  3. Use search tools (fzf, ripgrep) without installation failures
  4. Execute any task that requires the bin directory as a working directory

Background

I found this while looking for the root cause of #1809
At least for some first test it looks that I can now use the unsloth/Qwen3-Coder-30B-A3B-Instruct model without any problems.

Originally created by @florath on GitHub (Aug 12, 2025). ## Summary OpenCode fails with misleading `ENOENT: no such file or directory, posix_spawn` errors when performing operations that require subagents (like Write tool tasks). The root cause is that the `~/.local/share/opencode/bin` directory is extensively used throughout the codebase but is never created during initialization. ## Environment - **OS**: Linux (Debian 12) - **OpenCode Version**: 0.4.26 (npm installation) - **Installation Method**: `npm install -g opencode-ai` - **nvm**: upstream installation (not Debian) - **Node.js**: v20.19.4 (via nvm) ## Steps to Reproduce 1. Install nvm from upstream 2. Install opencode via npm: `npm install -g opencode-ai` 3. Start opencode in any directory: `opencode` 4. Try to perform any operation that requires the Write tool or subagent spawning 5. Example: Ask opencode to create a Python file like "Write tictactoe.py" ## Expected Behavior The operation should complete successfully, creating the requested file. ## Actual Behavior The operation fails with a misleading error: ``` ┃ Write tictactoe.py ┃ ┃ ┃ ┃ Error: ENOENT: no such file or directory, posix_spawn '/home/florath/.nvm/versions/node/v20.19.4/lib/node_modules/opencode-ai/node_modules/opencode-linux-x64/bin/opencode' ┃ ``` ## Debug Information ### strace Analysis Using `strace -f opencode` reveals the actual issue: ```bash [pid 253474] chdir("/home/florath/.local/share/opencode/bin") = -1 ENOENT (No such file or directory) [pid 253474] exit_group(127) = ? [pid 253474] +++ exited with 127 +++ [pid 253445] <... futex resumed>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal) [pid 253444] <... vfork resumed>) = 253474 [pid 253445] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=253474, si_uid=1000, si_status=127, si_utime=0, si_stime=0} --- [pid 253444] write(14, "ERROR 2025-08-12T08:02:39 +16ms service=default e=ENOENT: no such file or directory, posix_spawn '/home/florath/.nvm/versions/node/v20.19.4/lib/node_modules/opencode-ai/node_modules/opencode-linux-x64/bin/ opencode' rejection\n", 225) = 225 ``` **Key insight**: The error is NOT that the opencode binary doesn't exist, but that the process fails to `chdir` to `/home/florath/.local/share/opencode/bin` because that directory doesn't exist. ### Workaround Confirmation Creating the directory manually resolves the issue: ```bash mkdir -p ~/.local/share/opencode/bin ``` After creating this directory, all operations work correctly. ## Root Cause Analysis ### Directory Definition In `packages/opencode/src/global/index.ts`, the bin directory is defined but never created: ```typescript export namespace Global { export const Path = { data, bin: path.join(data, "bin"), // ← Defined here log: path.join(data, "log"), cache, config, state, } as const } await Promise.all([ fs.mkdir(Global.Path.data, { recursive: true }), fs.mkdir(Global.Path.config, { recursive: true }), fs.mkdir(Global.Path.state, { recursive: true }), fs.mkdir(Global.Path.log, { recursive: true }), // ← Global.Path.bin is NOT created here! ]) ``` ### Extensive Usage Without Creation The `Global.Path.bin` directory is used extensively throughout the codebase: **LSP Servers** (`packages/opencode/src/lsp/server.ts`): ```typescript // ESLint server installation const serverPath = path.join(Global.Path.bin, "vscode-eslint", "server", "out", "eslintServer.js") await $`unzip -o -q ${zipPath}`.cwd(Global.Path.bin).nothrow() // Go LSP server env: { ...process.env, GOBIN: Global.Path.bin } bin = path.join(Global.Path.bin, "gopls" + (process.platform === "win32" ? ".exe" : "")) // Ruby LSP server cmd: ["gem", "install", "ruby-lsp", "--bindir", Global.Path.bin] // And many more... ``` **Tools** (`packages/opencode/src/file/fzf.ts`, `packages/opencode/src/file/ripgrep.ts`): ```typescript // fzf installation Global.Path.bin, const archivePath = path.join(Global.Path.bin, filename) cwd: Global.Path.bin, // ripgrep installation filepath = path.join(Global.Path.bin, "rg" + (process.platform === "win32" ? ".exe" : "")) cwd: Global.Path.bin, ``` **All of these operations assume the directory exists, but it's never created.** ## Impact This bug affects: - ✗ Write tool operations that spawn subagents - ✗ LSP server installations (ESLint, gopls, ruby-lsp, pyright, etc.) - ✗ Tool downloads (fzf, ripgrep) - ✗ Any operation that uses `Global.Path.bin` as working directory - ✗ Task tool operations that require process spawning ## Proposed Fix Add the missing directory creation in `packages/opencode/src/global/index.ts`: ```typescript await Promise.all([ fs.mkdir(Global.Path.data, { recursive: true }), fs.mkdir(Global.Path.bin, { recursive: true }), // ← ADD THIS LINE fs.mkdir(Global.Path.config, { recursive: true }), fs.mkdir(Global.Path.state, { recursive: true }), fs.mkdir(Global.Path.log, { recursive: true }), ]) ``` ## Additional Notes - The error message is misleading because it suggests the opencode binary is missing, when actually it's a working directory issue - Setting `OPENCODE_BIN_PATH` environment variable does not help because the issue occurs before any subprocess spawning - This appears to be a long-standing oversight where the directory was defined and used but never actually created during initialization - which might highly depend on the used installation method. ## Verification After applying the fix, users should be able to: 1. Perform Write tool operations without errors 2. Use LSP features that require server installation 3. Use search tools (fzf, ripgrep) without installation failures 4. Execute any task that requires the bin directory as a working directory ## Background I found this while looking for the root cause of #1809 At least for some first test it looks that I can now use the `unsloth/Qwen3-Coder-30B-A3B-Instruct` model without any problems.
yindo closed this issue 2026-02-16 17:30:11 -05:00
Author
Owner

@devidasjadhav commented on GitHub (Aug 12, 2025):

I am facing similar issue even opencode binary exists.
Started noticing this after upgrade.

Edit mcp_server/src/mcp_server.py

Error: ENOENT: no such file or directory, posix_spawn '/home/dev/.opencode/bin/opencode'

I am still encountering issues with the edit tool. I will read the file again to ensure that the file path is correct and that I can access the file.
Build gemini-2.0-flash (04:07 PM)
```_
@devidasjadhav commented on GitHub (Aug 12, 2025): I am facing similar issue even opencode binary exists. Started noticing this after upgrade. ``` Edit mcp_server/src/mcp_server.py Error: ENOENT: no such file or directory, posix_spawn '/home/dev/.opencode/bin/opencode' I am still encountering issues with the edit tool. I will read the file again to ensure that the file path is correct and that I can access the file. Build gemini-2.0-flash (04:07 PM) ```_
Author
Owner

@rekram1-node commented on GitHub (Aug 12, 2025):

thx for spotting this

@rekram1-node commented on GitHub (Aug 12, 2025): thx for spotting this
Author
Owner

@AStarCale commented on GitHub (Jan 22, 2026):

I'm using bun on Windows 11 and the most current version of opencode and this error is still happening. I have created the folder. Maybe I have an older version installed. I tried the command opencode upgrade and got the following error:

●  Using method: bun
│
●  From 1.1.19 → 1.1.32
│
■  Upgrade failed
│
■  bun add v1.1.24 (85a32991)
│  error: Failed to link opencode-ai: EBUSY
│
│
└  Done

Update
I upgraded bun to the latest version and reinstalled bun and it appears to be working. Here is the PowerShell command:

powershell -c "irm bun.sh/install.ps1|iex"
bun add -g opencode-ai

No need to run opencode upgrade.

@AStarCale commented on GitHub (Jan 22, 2026): I'm using bun on Windows 11 and the most current version of opencode and this error is still happening. I have created the folder. Maybe I have an older version installed. I tried the command `opencode upgrade` and got the following error: ``` ● Using method: bun │ ● From 1.1.19 → 1.1.32 │ ■ Upgrade failed │ ■ bun add v1.1.24 (85a32991) │ error: Failed to link opencode-ai: EBUSY │ │ └ Done ``` **Update** I upgraded bun to the latest version and reinstalled bun and it appears to be working. Here is the PowerShell command: ``` powershell -c "irm bun.sh/install.ps1|iex" bun add -g opencode-ai ``` No need to run `opencode upgrade`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#1259