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

Resolved 💬 14 comments Opened Jan 21, 2026 by StreamDemon Closed May 10, 2026

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 ↗

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