Skip to content

[Bug] windows: claude runtime turns fail with spawn EINVAL (CLAUDE_CODE_EXECUTABLE set to a .cmd shim) #2397

Description

@jjgarciarovira

summary

on windows, every turn from a claude code agent fails with -32603 internal error, and the hidden detail is spawn EINVAL. the desktop sets CLAUDE_CODE_EXECUTABLE to the claude.cmd npm shim, and the adapter spawns it without shell: true. node >= 20.12 / 24 refuses to spawn a .cmd/.bat without a shell (the cve-2024-27980 hardening), so the spawn throws EINVAL. this is a sibling of the .cmd handling in #2247, and separate from the runtime path issue in #2327.

environment

  • os: windows 11
  • runtime: claude code, claude cli v2.1.217 (npm global, so the shim is %APPDATA%\npm\claude.cmd)
  • adapter: @agentclientprotocol/claude-agent-acp v0.60.0
  • node v24

what happens

buzz shows the agent's harness reported an internal error, and buzz-acp logs:

WARN buzz_acp: agent_returned (application error) outcome="error" configured_model=haiku error=Agent reported error (code -32603): Internal error

root cause

configure_runtime_cli (desktop/src-tauri/src/managed_agents/runtime.rs) does:

if let Some(cli_path) = runtime.underlying_cli.and_then(resolve_command) {
    command.env("CLAUDE_CODE_EXECUTABLE", cli_path);
}

for the claude runtime, resolve_command("claude") returns the npm shim ...\npm\claude.cmd. the adapter then spawns CLAUDE_CODE_EXECUTABLE, and on node >= 20.12/24 spawning a .cmd without shell: true throws spawn EINVAL.

note also that configure_runtime_cli runs after the user-env writes (runtime.rs ~line 1862, after merged_user_env at ~1859), so users can't override CLAUDE_CODE_EXECUTABLE from edit agent env vars.

reproduction

driving the adapter directly reproduces it:

CLAUDE_CODE_EXECUTABLE=<...>\claude.cmd   -> session/new -> {"code":-32603,"message":"Internal error","data":{"details":"spawn EINVAL"}}
CLAUDE_CODE_EXECUTABLE=""                 -> turn succeeds (adapter falls back to its bundled claude-code)

suggested fixes

  • on windows, resolve underlying_cli to a spawnable target (prefer a native claude.exe over the .cmd shim), or
  • spawn the executable with shell: true on windows, or
  • don't set CLAUDE_CODE_EXECUTABLE to a bare .cmd; leaving it unset makes the adapter use its bundled claude-code, which works fine.

workaround

install claude code's native binary so a real claude.exe is on path (irm https://claude.ai/install.ps1 | iex, lands at %USERPROFILE%\.local\bin\claude.exe). resolve_command prefers .exe over .cmd, so the adapter then spawns a real executable and turns succeed.

happy to open a pr if that would help!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions