-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
[Bug]: LSP tools fail on Windows with "Binary not found" despite correct installation and PATH configuration
Prerequisites
- I have searched existing issues and discussions to avoid duplicates
- This bug is specific to oh-my-opencode (not OpenCode core)
- I have read the documentation
- I have tested with the latest version (3.5.2)
Bug Description
All LSP tools (lsp_diagnostics, lsp_goto_definition, etc.) fail on Windows with:
Error: [LSP] Binary '{server-name}' not found on Windows.
Ensure the LSP server is installed and available in PATH.
This occurs even though:
- ✅ LSP servers are correctly installed via npm
- ✅ LSP servers are in PATH and executable
- ✅
oh-my-opencode doctorreports LSP servers as installed - ✅ Configuration is valid
Root Cause
The isBinaryAvailableOnWindows() function in src/tools/lsp/lsp-process.ts (lines 24-40, called at line 161) uses spawnSync("where", ...) to verify binary existence.
This check fails because OpenCode's Node.js subprocess doesn't inherit the full PATH environment from the user's shell, even though the same where command works perfectly when run in bash, cmd, PowerShell, or standalone Node.js scripts.
Additionally, this check is redundant — isServerInstalled() (from server-installation.ts) already validates binary existence before spawnProcess() is called, and it uses a more reliable PATH traversal method.
Environment
- oh-my-opencode version: 3.5.2
- OpenCode version: 1.1.60
- OS: Windows 11 (10.0.26220.7755)
- Platform: win32
- Node.js: v22.15.1
- Shell: Git Bash (MINGW64)
Steps to Reproduce
-
Install LSP servers via npm:
npm install -g yaml-language-server npm install -g typescript-language-server npm install -g vscode-markdown-language-server
-
Verify installation:
where yaml-language-server # Works - finds binary yaml-language-server --stdio # Works - starts server
-
Configure oh-my-opencode (already in default config):
{ "lsp": { "yaml": { "command": ["yaml-language-server", "--stdio"], "extensions": [".yaml", ".yml"] } } } -
Try to use LSP tools in OpenCode:
lsp_diagnostics(filePath="test.yaml") -
Expected: Get diagnostics
-
Actual: Error "Binary 'yaml-language-server' not found on Windows"
Evidence
1. LSP Servers Are Installed and Accessible
$ npm list -g yaml-language-server
C:\Users\[user]\AppData\Roaming\npm
└── [email protected]
$ where yaml-language-server
C:\Users\[user]\AppData\Roaming\npm\yaml-language-server
C:\Users\[user]\AppData\Roaming\npm\yaml-language-server.cmd
$ ls -la /c/Users/[user]/AppData/Roaming/npm/ | grep yaml
-rwxr-xr-x yaml-language-server
-rw-r--r-- yaml-language-server.cmd
-rwxr-xr-x yaml-language-server.ps12. where Command Works in All Contexts
Tested in:
- ✅ Git Bash:
where yaml-language-server→ status 0 - ✅ cmd.exe:
where yaml-language-server→ status 0 - ✅ PowerShell:
where.exe yaml-language-server→ status 0 - ✅ Node.js (all spawn options): status 0
// Test with exact oh-my-opencode spawn options
const result = spawnSync("where", ["yaml-language-server"], {
shell: true,
windowsHide: true,
timeout: 5000,
});
console.log(result.status); // 0 (success)3. Both Detection Functions Work Standalone
Created reproduction script testing both isServerInstalled() and isBinaryAvailableOnWindows():
yaml-language-server:
isServerInstalled(): true
isBinaryAvailableOnWindows(): true
Would LSP work? true
typescript-language-server:
isServerInstalled(): true
isBinaryAvailableOnWindows(): true
Would LSP work? true
Reproduction script: [attached]
4. Bug Affects ALL LSP Servers
Not just yaml-language-server:
lsp_diagnostics("test.yaml") → "Binary 'yaml-language-server' not found"
lsp_diagnostics("test.md") → "Binary 'vscode-markdown-language-server' not found"
lsp_diagnostics("test.ts") → "Binary 'typescript-language-server' not found"
Even though oh-my-opencode doctor reports:
✓ LSP Servers → 2/4 servers available
• Installed: typescript-language-server
• Installed: pyright
5. Configuration Is Valid
$ oh-my-opencode doctor
✓ Configuration Validity → Valid JSON config
✓ LSP Servers → 2/4 servers available
# oh-my-opencode.json contains:
{
"lsp": {
"yaml": {
"command": ["yaml-language-server", "--stdio"],
"extensions": [".yaml", ".yml"]
},
"typescript": { ... },
"markdown": { ... }
}
}Proposed Solution
Remove lines 161-166 in src/tools/lsp/lsp-process.ts:
// REMOVE THIS:
if (!isBinaryAvailableOnWindows(cmd)) {
throw new Error(
`[LSP] Binary '${cmd}' not found on Windows. ` +
`Ensure the LSP server is installed and available in PATH. ` +
`For npm packages, try: npm install -g ${cmd}`
)
}Rationale:
- Redundant:
isServerInstalled()already validated the binary exists earlier in the call chain (beforegetClient()callsspawnProcess()) - More reliable:
isServerInstalled()uses PATH traversal with proper extension checking (.cmd,.bat,.ps1) - Unreliable:
isBinaryAvailableOnWindows()depends onwherecommand having access to full PATH in subprocess, which varies by environment
Workaround
Users can work around this by using absolute paths in configuration:
{
"lsp": {
"yaml": {
"command": [
"C:\\Users\\[user]\\AppData\\Roaming\\npm\\yaml-language-server.cmd",
"--stdio"
]
}
}
}This bypasses the where check (line 27 checks for \ and uses existsSync instead).
Additional Context
This is a Windows-specific PATH inheritance issue in subprocess environments. The exact same isBinaryAvailableOnWindows() code works perfectly in standalone Node.js scripts but fails when called from within OpenCode's plugin context.
Related historical issues:
- [Bug][v3.0.0-beta.15]: Bun crashed when using LSP(lsp_diagnostics) on Windows #1047: Bun crashed when using LSP on Windows
- Windows LSP blocked: Binary bundled with Bun v1.3.5 despite system having v1.3.8+ #1503: LSP blocked due to Bun version check
- fix(lsp): use Node.js child_process on Windows to avoid Bun spawn segfault #1510: Use Node.js child_process to avoid Bun segfault
- LSP tools blocked on Windows due to embedded Bun 1.3.5 in precompiled binary #1558: LSP tools blocked due to embedded Bun version
Reproduction Script
#!/usr/bin/env node
const { spawnSync } = require('child_process');
const { existsSync } = require('fs');
// [Full script from reproduce-lsp-bug.js]Doctor Output
$ oh-my-opencode doctor --verbose
Installation
────────────────────────────────────────
✓ OpenCode Installation → 1.1.60
✓ Plugin Registration → Registered
Configuration
────────────────────────────────────────
✓ Configuration Validity → Valid JSON config
✓ Model Resolution → 10 agents, 8 categories
Tools & Servers
────────────────────────────────────────
✓ LSP Servers → 2/4 servers available
• Installed: typescript-language-server
• Installed: pyright
• Not found: rust-analyzer (optional)
• Not found: gopls (optional)
Note: Doctor only checks 4 servers (typescript, pyright, rust, gopls) but doesn't check yaml-language-server, markdown-language-server, etc.
Tested with: oh-my-opencode 3.5.2 (latest as of 2026-02-12)