LSP plugins fail on Windows: spawn ENOENT for npm global shim scripts

Resolved 💬 3 comments Opened Mar 23, 2026 by wtfet Closed Mar 27, 2026

Bug Description

All LSP plugins (pyright-lsp, typescript-lsp, etc.) fail on Windows because Claude Code uses child_process.spawn() without shell: true to launch LSP server binaries. On Windows, npm installs global packages as shell shim scripts (.cmd/.ps1/bash), not native executables, so spawn() fails with ENOENT.

Environment

  • OS: Windows 11 Enterprise 10.0.26200
  • Claude Code: Latest (auto-updates enabled)
  • Shell: Git Bash
  • Node.js: Installed via official installer
  • Pyright: 1.1.408 (npm global)
  • typescript-language-server: 5.1.3 (npm global)

Reproduction

  1. Install pyright globally: npm install -g pyright
  2. Install the pyright-lsp plugin from claude-plugins-official
  3. Enable LSP: ENABLE_LSP_TOOL: "1" in settings
  4. Use the LSP tool on any .py file

On local paths:

Error performing documentSymbol: Failed to sync file open C:\...\file.py: Cannot send notification to LSP server 'plugin:pyright-lsp:pyright': server is error

On UNC paths:

Error performing documentSymbol: ENOENT: no such file or directory, uv_spawn 'pyright-langserver'

Root Cause (Confirmed)

Node.js spawn('pyright-langserver', ['--stdio']) without shell: true fails on Windows because:

  1. pyright-langserver in npm global bin is a bash shell script shim, not a native .exe
  2. pyright-langserver.cmd exists but spawn() doesn't try .cmd extensions without shell: true
  3. libuv's uv_spawn cannot execute shell scripts directly

Proof: Running spawn('pyright-langserver', ['--stdio'], { shell: true }) successfully outputs "Pyright language server 1.1.408 starting".

Configuration (All Correct)

  • settings.json: ENABLE_LSP_TOOL: "1", plugin enabled
  • Marketplace lspServers.pyright config: command: "pyright-langserver", args: ["--stdio"]
  • Binary exists at C:\Users\...\AppData\Roaming\npm\pyright-langserver (+ .cmd, .ps1)
  • npm global bin is in PATH

Fix

Add shell: true to the spawn() options when launching LSP servers on Windows, or detect and use the .cmd shim directly. This affects all LSP plugins, not just pyright.

Affected Plugins

All LSP plugins in claude-plugins-official:

  • pyright-lsp, typescript-lsp, clangd-lsp, csharp-lsp, gopls-lsp, jdtls-lsp, kotlin-lsp, lua-lsp, php-lsp, ruby-lsp, rust-analyzer-lsp, swift-lsp

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗