claude-code - 💡(How to fix) Fix Ctrl+G $EDITOR on Windows: spawn EINVAL on .cmd shims (CVE-2024-27980)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

Error Messages/Logs

Claude Code's Ctrl+G handler effectively does spawn(process.env.EDITOR, [tempPath]) without shell: true. When $EDITOR resolves to a .cmd path, Node rejects the spawn; the exception is caught and surfaced via the status line.

  • #48950 — "Open exited with code 1" on macOS. Different platform and root cause (compound $EDITOR parsing) but the same error-message template; both may benefit from an editor-invocation refactor.

Root Cause

Since Node 18.20.0 / 20.12.0 / 21.7.0 (CVE-2024-27980, April 2024), child_process.spawn('<file>.cmd', ...) synchronously throws EINVAL unless shell: true is passed.

Claude Code's Ctrl+G handler effectively does spawn(process.env.EDITOR, [tempPath]) without shell: true. When $EDITOR resolves to a .cmd path, Node rejects the spawn; the exception is caught and surfaced via the status line.

Fix Action

Fix / Workaround

Not directly — but the workaround recommended in the closed issue #29406 ("wrap your editor in a .cmd") is exactly what this bug now blocks, so for users following that advice it manifests as a silent regression.

N/A (the underlying Node mitigation has been live since April 2024; this path was likely never exercised against post-CVE Node on Windows with a .cmd $EDITOR).

  • #27061 — LSP plugins ENOENT, missing shell: true for .cmd
  • #51191 — typescript-lsp ENOENT on .cmd shims
  • #53814 — LSP fails to spawn npm-installed .cmd binaries
  • #17136, #19536 — earlier TypeScript-LSP variants
  • #29406 — $EDITOR paths with spaces on Windows. The accepted workaround in that thread is what this bug now blocks.

Code Example

<editor>.cmd quit unexpectedly (exit code 1)

---

// spawn-test.mjs
import { spawn } from 'node:child_process';
try {
  spawn('C:\\Users\\me\\AppData\\Roaming\\npm\\my-editor.cmd',
        ['C:\\tmp\\foo.txt'], { stdio: 'inherit' });
} catch (e) {
  console.log('sync throw:', e.code, e.message);
}

---

> node spawn-test.mjs
sync throw: EINVAL spawn EINVAL

---

// current
spawn(editor, args)

// option 1
spawn(editor, args, { shell: true })

// option 2 (preferred — avoids shell metacharacter pitfalls)
spawn('cmd', ['/c', editor, ...args])
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet (closest matches in Additional Information)
  • This is a single bug report
  • I am using the latest version of Claude Code (2.1.132)

What's Wrong?

On Windows, pressing Ctrl+G in Claude Code's chat input fails immediately with:

<editor>.cmd quit unexpectedly (exit code 1)

The editor never launches; the .cmd body is never executed (verifiable: prepend dir > C:\tmp\trace.txt to the shim — no file appears). Reproduces with any $EDITOR whose path ends in .cmd, including every npm-installed wrapper shim. Linux is unaffected because $EDITOR there is typically a shell script with a shebang, which uses a different code path.

What Should Happen?

Pressing Ctrl+G should launch the configured external editor and load the chat-input contents into a temp file for editing — same as on Linux/macOS.

Error Messages/Logs

<editor>.cmd quit unexpectedly (exit code 1)

Steps to Reproduce

  1. On Windows with Node ≥ 18.20.0 (or 20.12.0 / 21.7.0), set $EDITOR to any .cmd file (an npm-installed wrapper, or a hand-written .cmd that calls a real editor).
  2. Launch Claude Code.
  3. Press Ctrl+G in the chat input.

Result: the status line shows <editor>.cmd quit unexpectedly (exit code 1) instantly. The shim's first line never runs.

Standalone reproducer (no Claude Code involvement)

// spawn-test.mjs
import { spawn } from 'node:child_process';
try {
  spawn('C:\\Users\\me\\AppData\\Roaming\\npm\\my-editor.cmd',
        ['C:\\tmp\\foo.txt'], { stdio: 'inherit' });
} catch (e) {
  console.log('sync throw:', e.code, e.message);
}
> node spawn-test.mjs
sync throw: EINVAL spawn EINVAL

The same .cmd invoked through cmd.exe directly runs fine, proving the shim is healthy. Only child_process.spawn without shell: true refuses it.

Root cause

Since Node 18.20.0 / 20.12.0 / 21.7.0 (CVE-2024-27980, April 2024), child_process.spawn('<file>.cmd', ...) synchronously throws EINVAL unless shell: true is passed.

Claude Code's Ctrl+G handler effectively does spawn(process.env.EDITOR, [tempPath]) without shell: true. When $EDITOR resolves to a .cmd path, Node rejects the spawn; the exception is caught and surfaced via the status line.

Suggested fix

One-line change in the Ctrl+G editor-launch code:

// current
spawn(editor, args)

// option 1
spawn(editor, args, { shell: true })

// option 2 (preferred — avoids shell metacharacter pitfalls)
spawn('cmd', ['/c', editor, ...args])

Is this a regression?

Not directly — but the workaround recommended in the closed issue #29406 ("wrap your editor in a .cmd") is exactly what this bug now blocks, so for users following that advice it manifests as a silent regression.

Last Working Version

N/A (the underlying Node mitigation has been live since April 2024; this path was likely never exercised against post-CVE Node on Windows with a .cmd $EDITOR).

Claude Code Version

2.1.132

Platform

Anthropic API

Operating System

Windows 11

Terminal/Shell

Reproduces in any Windows console (Windows Terminal + PowerShell, cmd.exe, Git Bash). Independent of the host shell, because the failure is in Claude Code's own spawn call, not the shell.

Additional Information

Adjacent closed issues — same root-cause family. The LSP-spawn path received the shell: true fix, but the Ctrl+G / $EDITOR path apparently didn't:

  • #27061 — LSP plugins ENOENT, missing shell: true for .cmd
  • #51191 — typescript-lsp ENOENT on .cmd shims
  • #53814 — LSP fails to spawn npm-installed .cmd binaries
  • #17136, #19536 — earlier TypeScript-LSP variants
  • #29406 — $EDITOR paths with spaces on Windows. The accepted workaround in that thread is what this bug now blocks.

Possibly related:

  • #48950 — "Open exited with code 1" on macOS. Different platform and root cause (compound $EDITOR parsing) but the same error-message template; both may benefit from an editor-invocation refactor.
  • #51363 — Ctrl+G external editor on Windows: arrow-key forwarding (different bug, same surface).

Reproduced 2026-05-05 on Windows 11 / Node v25.4.0.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING