Skip to content

Bug: LSP server spawn doesn't use the same PATH resolution as isServerInstalled() #2431

@aaajiao

Description

@aaajiao

Summary

isServerInstalled() checks 4 additional paths beyond $PATH (including cwd/node_modules/.bin/), but spawnProcess() only uses process.env.PATH. This causes LSP servers that are detected as "installed" to fail at spawn time with a "not found" error.

Reproduction

  1. Install biome as a project dependency: npm install @biomejs/biome
  2. Do NOT install biome globally
  3. Confirm binary exists: ls ./node_modules/.bin/biome → exists
  4. Run lsp_diagnostics on a .ts file
  5. Expected: biome LSP starts successfully (since isServerInstalled finds it in node_modules/.bin/)
  6. Actual: Error: Executable not found in $PATH: "biome"

Root Cause

Detection (server-installation.tsisServerInstalled)

Checks these paths (broad):

// 1. System PATH
// 2. cwd/node_modules/.bin/        ← finds biome here ✅
// 3. configDir/bin/
// 4. configDir/node_modules/.bin/
// 5. dataDir/bin/

Spawn (lsp-client-transport.tsstart())

Uses only process.env (narrow):

this.proc = spawnProcess(this.server.command, {
    cwd: this.root,
    env: {
        ...process.env,        // ← only system PATH, no additionalBases
        ...this.server.env
    }
});

The additionalBases from isServerInstalled are completely ignored during spawn.

Suggested Fix

In lsp-client-transport.ts, augment the spawn env's PATH with the same additional paths that isServerInstalled checks:

// Option A: Add node_modules/.bin to spawn PATH
const extraPaths = [
    path.join(this.root, "node_modules", ".bin"),
    path.join(configDir, "bin"),
    path.join(configDir, "node_modules", ".bin"),
    path.join(dataDir, "bin"),
];
const augmentedPath = [...extraPaths, process.env.PATH].filter(Boolean).join(":");

this.proc = spawnProcess(this.server.command, {
    cwd: this.root,
    env: {
        ...process.env,
        ...this.server.env,
        PATH: augmentedPath,
    }
});

Or alternatively, resolve the full binary path in isServerInstalled and pass the absolute path to spawn.

Environment

  • oh-my-opencode version: latest (as of 2026-03-10)
  • Runtime: Bun (Linux arm64, Docker)
  • Affected server: biome (but applies to any LSP server installed only in node_modules/.bin/)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions