/ide fails on Windows Server 2019 via RDP: process ancestry check breaks IDE connection after extension reload
Summary
When running Claude Code in a VS Code terminal on Windows Server 2019 via RDP, the /ide command fails with _"Failed to connect to Visual Studio Code."_ after VS Code reloads the extension host (e.g. after Developer: Reload Window or an extension update). The connection cannot be restored without starting a completely new Claude session.
Environment
- OS: Windows Server 2019 Standard (10.0.17763), session via RDP (
RDP-Tcp#XX) - Claude Code CLI: 2.1.119
- VS Code Extension: anthropic.claude-code 2.1.119
- VS Code: 1.117.0
Steps to reproduce
- Open VS Code on Windows Server 2019 via RDP.
- Start a Claude Code terminal from VS Code (extension injects
CLAUDE_CODE_SSE_PORT=<portA>). - Begin a Claude Code session — IDE connection works initially.
- Reload the VS Code window (
Developer: Reload Window) or let the extension update/restart. - The extension now starts a new MCP server on a different port
<portB>and writes~/.claude/ide/<portB>.lock. - Run
/idein the existing terminal → "Failed to connect to Visual Studio Code."
Root cause
The IDE discovery function in the CLI performs a process-ancestry check when the port in CLAUDE_CODE_SSE_PORT (stale: <portA>) does not match the port in the lock file (<portB>):
// Simplified from CLI source
if (!(K !== null && M.port === K)) { // port mismatch → enters check
if (!M.pid || !FpK(M.pid)) continue;
if (process.ppid !== M.pid) {
if (!(await z()).has(M.pid)) continue; // ← fails on RDP
}
}
The check passes only if the lock file's pid (written as process.ppid by the extension host, e.g. 14416) is found in the Claude process's ancestor chain.
On Windows Server via RDP, the ancestor chain is truncated. Debugging shows:
Claude process chain: 9776 → 12340
Lock file pid (14416) in chain: false
The chain stops at 2 levels and never reaches the VS Code process, so the valid lock file is discarded and the function returns [].
The check IS correctly bypassed when K === M.port (i.e. when CLAUDE_CODE_SSE_PORT matches the lock file port). But since process.env is a startup snapshot in Node.js, export CLAUDE_CODE_SSE_PORT=<portB> in the parent shell has no effect on the already-running Claude process.
Expected behavior
/ide should reconnect to the active VS Code instance as long as a valid lock file exists for the current workspace, regardless of whether the Claude process can trace VS Code in its ancestor chain.
Workaround
Start a completely new Claude terminal from VS Code after each extension reload. The extension injects the current port into the new terminal's environment, so the K === M.port path is taken and the ancestry check is skipped.
Suggested fix
Consider one of:
- Relax the ancestry check on Windows when
runningInWindows: trueis set in the lock file and the workspace folder matches — RDP sessions commonly break the expected process tree. - Re-read
CLAUDE_CODE_SSE_PORTfrom the lock directory at/idetime instead of relying solely on the startup environment, so/idecan discover a new port even in a stale session. - Honour
CLAUDE_CODE_IDE_SKIP_VALID_CHECKas a full bypass (currently it only setsisValid=truebut the ancestry check still runs via theYblock and discards the entry withcontinue).
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗