Problem
On Windows, any LSP plugin server fails on startup with:
ENOENT: no such file or directory, uv_spawn 'typescript-language-server'
This affects all LSP plugins (typescript-lsp, pyright-lsp, etc.) on Windows.
Root Cause
spawnLspServerProcess() in src/agents/pi-bundle-lsp-runtime.ts calls child_process.spawn(config.command, ...) directly. On Windows, npm installs CLI tools as .cmd wrapper scripts. Node.js spawn() without shell: true uses CreateProcess under the hood, which cannot find or execute .cmd files — even when they are present in PATH.
Why It Works on Mac/Linux
On macOS/Linux, npm installs a proper executable shim (a shell script with a shebang). Node.js spawn() can execute these directly. On Windows, only a .cmd file is installed, which requires shell mediation.
Fix
resolveWindowsSpawnProgram() already exists in src/plugin-sdk/windows-spawn.ts and handles this exactly — it finds the .cmd shim via PATH+PATHEXT, parses it to extract the real Node.js entrypoint, and returns a direct spawn invocation that requires no shell. It is already used for Docker and memory-host spawning but was not wired into the LSP spawn path.
See PR #75343 which applies this fix.
Environment
- OS: Windows 11
- Node.js: v22.14.0
- Affected plugin: typescript-lsp (and likely all LSP plugins)
Problem
On Windows, any LSP plugin server fails on startup with:
This affects all LSP plugins (typescript-lsp, pyright-lsp, etc.) on Windows.
Root Cause
spawnLspServerProcess()insrc/agents/pi-bundle-lsp-runtime.tscallschild_process.spawn(config.command, ...)directly. On Windows, npm installs CLI tools as.cmdwrapper scripts. Node.jsspawn()withoutshell: trueusesCreateProcessunder the hood, which cannot find or execute.cmdfiles — even when they are present inPATH.Why It Works on Mac/Linux
On macOS/Linux, npm installs a proper executable shim (a shell script with a shebang). Node.js
spawn()can execute these directly. On Windows, only a.cmdfile is installed, which requires shell mediation.Fix
resolveWindowsSpawnProgram()already exists insrc/plugin-sdk/windows-spawn.tsand handles this exactly — it finds the.cmdshim via PATH+PATHEXT, parses it to extract the real Node.js entrypoint, and returns a direct spawn invocation that requires no shell. It is already used for Docker and memory-host spawning but was not wired into the LSP spawn path.See PR #75343 which applies this fix.
Environment