typescript-lsp plugin fails on Windows: spawn ENOENT for npm global binaries

Status Closed — duplicate
Reported on v2.1.14
Maintainer reply ✓ Yes — claude[bot]
Activity 15 comments · opened Jan 21, 2026 · closed May 10, 2026
💡 Likely answer: A maintainer (claude[bot], contributor) responded on this thread — see the highlighted reply below.

Description

The typescript-lsp plugin fails to start on Windows with the error:

LSP server plugin:typescript-lsp:typescript failed to start: ENOENT: no such file or directory, uv_spawn 'typescript-language-server'

Root Cause

On Windows, npm installs global packages with .cmd wrapper scripts (batch files), not executable binaries. When Claude Code's LSP manager uses Node.js spawn() without shell: true, it cannot find the .cmd files because:

  1. Node.js spawn() without shell only looks for actual executables (.exe)
  2. npm creates typescript-language-server.cmd (batch file), not typescript-language-server.exe
  3. While cmd.exe respects PATHEXT and finds .cmd files, Node.js spawn() does not

Reproduction

// This fails on Windows:
const { spawn } = require('child_process');
spawn('typescript-language-server', ['--version']); // ENOENT

// This works:
spawn('typescript-language-server', ['--version'], { shell: true }); // OK
spawn('typescript-language-server', ['--version'], { shell: 'cmd.exe' }); // OK

Environment

  • OS: Windows 11 (build 26220)
  • Claude Code: 2.1.14
  • Node.js: 24.3.0
  • typescript-language-server: 5.1.3 (installed globally via npm)

Suggested Fix

The LSP manager should use shell: true (or shell: 'cmd.exe') when spawning language servers on Windows. This allows the shell to resolve .cmd wrapper scripts.

Alternatively, the plugin could explicitly look for the .cmd extension on Windows:

const command = process.platform === 'win32' 
  ? 'typescript-language-server.cmd' 
  : 'typescript-language-server';

Workaround

Created a .NET shim executable (typescript-language-server.exe) that calls the .cmd file via cmd.exe. This allows Node.js spawn() to find and execute it.

View original on GitHub ↗

14 Comments

github-actions[bot] · 7 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/19536
  2. https://github.com/anthropics/claude-code/issues/17718
  3. https://github.com/anthropics/claude-code/issues/17136

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

pdebuitlear · 7 months ago

There are multiple dupes of this issue that affects multiple LSP plugins. Multiple of these dupes, like this defect have suggested fixes. Why aren't these fixes being implemented?

AsysKevin · 6 months ago

I encountered the same issue on Windows 11 (Build 10.0.26200.7628) with Claude Code 2.1.31.

Root Cause Analysis:

On Windows, npm installs global packages with .cmd batch wrapper scripts (e.g., typescript-language-server.cmd) instead of .exe executables. Node.js's spawn() function, without shell: true option, only looks for actual executables (.exe), causing the ENOENT error.

Suggested Fix:

When spawning LSP servers on Windows, either:

  • Use shell: true option in spawn()
  • Or explicitly look for .cmd files on Windows platform

This affects not just TypeScript LSP but potentially any npm-installed language server.

HaNagid · 6 months ago

Workaround: Edit marketplace.json directly

Found a fix for this on Windows. The issue is that typescript-language-server is installed as a .cmd file at AppData\Roaming\npm\typescript-language-server.cmd, and Node.js spawn() can't resolve .cmd files without shell: true.

User-side workaround:

Edit ~/.claude/plugins/marketplaces/claude-plugins-official/.claude-plugin/marketplace.json and change the typescript-lsp entry from:

"command": "typescript-language-server",
"args": ["--stdio"],

to:

"command": "cmd",
"args": ["/c", "typescript-language-server", "--stdio"],

Restart Claude Code. LSP diagnostics should start working — confirmed on Windows 10 with Claude Code 2.1.38 (native binary).

Note: You may also need "ENABLE_LSP_TOOL": "1" in your ~/.claude/settings.json env block.

The proper upstream fix would be adding shell: true (or { shell: 'cmd.exe' }) to the spawn() call when process.platform === 'win32' — this would fix it for all npm-installed language servers on Windows, not just TypeScript.

See also #15202 for the related timing bug where LSP manager initializes before plugins finish loading.

pdebuitlear · 6 months ago

Still reproduces as of 2.1.45

klunejko · 6 months ago

still the case with 2.1.63

Ramy0001 · 5 months ago

@HaNagid thanks man, your fix works for typescript lsp, is there a similar fix for python lsp ?

beanc16 · 5 months ago

Still an issue for me as well.
Claude Code version: 2.1.81
OS: Windows 11 Pro (Build 26200)
Shell: Git Bash (MSYS2)
Node: v20.18.0 (via nvm4w)
npm: 10.8.2

Confirming that @HaNagid's workaround worked for me too 😄 Hope this gets an official fix so Windows users can have typescript-lsp work off-the-shelf without tracking down this issue.

JvdsReform · 5 months ago

Still an issue on my end as wel on version 2.1.83

testPerfDave · 5 months ago

Is this issue being worked on or is this another confirmation that LLM without proper engineers is an ongoing trainwreck that's going to cause a complete breakdown of society due to the competency crisis?

tomhillgreyridge · 4 months ago

---
Workaround for Windows LSP plugin ENOENT (tested with php-lsp, should work for all npm-installed LSP servers)

Root cause: On Windows, npm install -g creates .cmd batch wrappers (e.g. intelephense.cmd), not .exe executables.
Node.js child_process.spawn() without shell: true only resolves .exe files via PATHEXT, so spawn('intelephense') fails
with ENOENT even though intelephense.cmd exists and works fine from a terminal.

Workaround: Create a plugin.json in the cached plugin directory that wraps the command with cmd /c, which lets cmd.exe
handle the .cmd resolution:

  1. Create the directory:

mkdir -p ~/.claude/plugins/cache/claude-plugins-official/php-lsp/1.0.0/.claude-plugin

  1. Create plugin.json in that directory with these contents:

```json
{
"name": "php-lsp",
"version": "1.0.0",
"description": "PHP language server (Intelephense) for code intelligence",
"author": {
"name": "Anthropic",
"email": "support@anthropic.com"
},
"lspServers": {
"intelephense": {
"command": "cmd",
"args": ["/c", "intelephense", "--stdio"],
"extensionToLanguage": {
".php": "php"
}
}
}
}

  3. Run /reload-plugins in Claude Code.

  The same pattern works for any affected LSP plugin — just adjust the plugin name in the path and the binary name in
  args. For example, for typescript-lsp you'd use "args": ["/c", "typescript-language-server", "--stdio"].

  Caveat: If the plugin auto-updates, the cache directory may be wiped and you'll need to recreate the file.

  Environment: Windows 11, Claude Code with php-lsp@claude-plugins-official, intelephense 1.16.5 installed via npm
  install -g.

  Obviously, the correct long term fix is for Anthropic to sort this since it is an obvious bug
claude[bot] contributor · 3 months ago

This is a duplicate of #17312, which was fixed as of version 2.1.132.

r1skie · 3 months ago
This is a duplicate of #17312, which was fixed as of version 2.1.132.

It wasn't fixed.

muckybuzzwoo · 2 months ago

Still broken in v2.1.161 on Windows 11 — affects both typescript-lsp and php-lsp

Confirming the issue persists on:

  • Claude Code 2.1.161 (Windows 11 Home)
  • typescript-language-server@5.3.0 and intelephense@1.18.4 installed globally via npm
  • C:\Users\<user>\AppData\Roaming\npm present in Windows user PATH

Both typescript-lsp@claude-plugins-official and php-lsp@claude-plugins-official fail identically:

ENOENT: no such file or directory, uv_spawn 'typescript-language-server'
ENOENT: no such file or directory, uv_spawn 'intelephense'

The .cmd workaround (editing marketplace.json) does resolve the issue but gets overwritten on marketplace updates — so it's not a viable long-term solution. cross-spawn or shell: true on Windows would be a one-line fix on Anthropic's side.

Showing cached comments. Read the full discussion on GitHub ↗