Skip to content

fix(staged): keep ACP agent alive by pinning its dir on PATH + log stderr#760

Merged
matt2e merged 1 commit into
mainfrom
fix/acp-node-path-and-stderr
Jun 2, 2026
Merged

fix(staged): keep ACP agent alive by pinning its dir on PATH + log stderr#760
matt2e merged 1 commit into
mainfrom
fix/acp-node-path-and-stderr

Conversation

@matt2e

@matt2e matt2e commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Starting a Claude ACP session in the staged app could fail with an opaque error:

ACP init failed: Error { code: -32603: Internal error, message: "Internal error", data: Some(String("server shut down unexpectedly")) }

The agent subprocess was dying before responding to the initialize handshake. Root cause: claude-agent-acp is a #!/usr/bin/env node script, and the agent is exec'd inside the session's working directory through a clean-env (env_clear) login shell. If that directory's shell init doesn't put a compatible node on PATH (Hermit/direnv can replace PATH, nvm may not activate), the shebang fails with env: node: No such file or directory (exit 127) and the process exits instantly. Its stdout closes before the initialize response → the client reports "server shut down unexpectedly".

It was hard to diagnose because the agent's stderr was sent to /dev/null, hiding the real env: node: ... message.

Not a version issue: claude-agent-acp 0.39.0 is the latest, and the negotiated protocol version (ProtocolVersion::LATEST = V1) matches what the agent speaks.

Fix

In crates/acp-client/src/driver.rs:

  1. Pin the agent binary's directory on PATH for the exec. The exec line is now exec env PATH=<binary_dir>:"$PATH" <binary> <args>. Since the resolved binary lives in a node bin dir that also contains node, this guarantees the shebang's interpreter is always found regardless of what the session dir's shell init does. Falls back to the plain form if the binary has no parent dir.

  2. Stop discarding the agent's stderr. Changed Stdio::null()Stdio::piped() and drain it line-by-line into log::warn! (tagged with agent label + session id). Future spawn/shebang/shell-init failures are now visible instead of vanishing.

Verification

  • cargo check and cargo test -p acp-client pass (16 tests).
  • Reproduced the original failure (env: node: No such file or directory, exit 127) with node stripped from PATH, then confirmed the new exec line negotiates initialize successfully under the same stripped PATH.

🤖 Generated with Claude Code

…derr

Starting a Claude ACP session could fail with an opaque "ACP init failed:
server shut down unexpectedly". The agent subprocess was dying before the
`initialize` response because `claude-agent-acp` is a `#!/usr/bin/env node`
script, and the session working directory's clean-env login shell did not
always expose a compatible `node` on PATH (Hermit/direnv can replace PATH,
nvm may not activate). The shebang then failed with `env: node: No such
file or directory` and the process exited instantly.

Two fixes:

- Prepend the resolved agent binary's own directory to PATH in the `exec`
  line so the interpreter that ships alongside the binary is always found,
  regardless of the session dir's shell init.
- Stop discarding the agent's stderr (was `Stdio::null`); pipe it and drain
  it to the log. The failed-shebang message and any shell-init errors are
  now visible instead of surfacing only as "server shut down unexpectedly".

Not a version issue: claude-agent-acp 0.39.0 is current and the negotiated
protocol version (V1) matches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@matt2e matt2e requested review from baxen and wesbillman as code owners June 2, 2026 05:10
@matt2e matt2e merged commit 5d234a4 into main Jun 2, 2026
7 checks passed
@matt2e matt2e deleted the fix/acp-node-path-and-stderr branch June 2, 2026 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant