Summary
When the Claude CLI on the user's machine is incompatible with the bundled claude-agent-acp adapter (in my case: CLI 2.0.25 does not support the --tools flag that adapter 0.60.0 passes), every session/new fails instantly. The adapter reports the precise cause in the JSON-RPC error's data field:
{"jsonrpc":"2.0","id":2,"error":{"code":-32603,"message":"Internal error",
"data":{"details":"Claude Code process exited with code 1. stderr: error: unknown option '--tools'"}}}
buzz-acp discards error.data when constructing AcpError::AgentError (only code and message survive — crates/buzz-acp/src/acp.rs:111-121), so the harness log and the user-facing channel notice both reduce to:
⚠️ I couldn't process the last request after multiple retries (Agent reported error (code -32603): Internal error). Please re-send if it's still needed.
Because AgentError is classified as an application-class error ("session is healthy — don't invalidate", crates/buzz-acp/src/pool.rs:2169; no respawn, handle_prompt_result in crates/buzz-acp/src/lib.rs), the harness retries the hopeless spawn with backoff (10 attempts, 5s→300s) for every incoming message, dead-letters each batch, and never recovers or escalates. All managed agents on the machine (three in my case) wedge identically and indefinitely.
The failure is deterministic and permanent, yet the user experience is an unexplained "Internal error" that looks transient. In my case it presented as "my agents died when I hit my Claude usage limit and never came back" — the actual trigger was that fresh CLI spawns resolved a different (older) claude binary than the still-running processes from the previous day, so everything kept working until the app restarted.
Confirmed: upgrading the CLI (npm install -g @anthropic-ai/claude-code@latest) and restarting the agents fully restores them — the version mismatch was the sole cause.
Environment
- Packaged macOS desktop build (
xyz.block.buzz.app), three managed Claude agents
- Bundled adapter:
@agentclientprotocol/claude-agent-acp 0.60.0 (Buzz node-tools, bundled node v24.11.0)
- User CLI: Claude Code 2.0.25 (npm global under nvm node v22.16.0) — works fine standalone (
claude -p succeeds); does not support --tools
- Code refs against
main @ aaf48fc
Reproduction
- Install a Claude Code CLI version that predates the
--tools flag (e.g. 2.0.25) as the claude the login shell resolves.
- Run any managed Claude agent and mention it in a channel.
- Harness log shows only
agent_returned (application error — pipe intact) … error=Agent reported error (code -32603): Internal error × 10 with backoff, then dead-lettering batch after 10 retries.
- Drive the adapter directly with an ACP handshake (initialize → session/new) to see the real error in
error.data.details (probe transcript above).
Root causes
- Diagnostic loss:
acp.rs agent_error_from_json keeps code + message, drops data. Per JSON-RPC 2.0, data is exactly where servers put the useful detail; the claude adapter uses it for the subprocess's stderr.
- No escalation for deterministic failures: application-class
AgentError never invalidates the session, never respawns, never trips the circuit breaker, and never varies its handling no matter how many consecutive identical failures occur — so a permanent config problem is retried forever as if transient.
- No compatibility preflight: desktop discovery verifies the underlying CLI exists (and probes auth) but not that its version is compatible with the bundled adapter, so a stale/shadowed
claude (nvm per-node-version globals make this easy) fails only at session-spawn time, with the message from (1).
Suggested fixes
- Append
error.data (stringified, truncated) to AcpError::AgentError's Display and to the turn_error observer payload — one-line-ish change that would have made this self-diagnosing.
- Track consecutive
AgentErrors per agent; after N identical failures, invalidate the session, then respawn the slot, then trip SlotCircuit — and surface a distinct user-facing notice ("agent failed N times with: Details
") instead of the generic retry text.
- At spawn (or in discovery), run
claude --version against the resolved CLAUDE_CODE_EXECUTABLE and check it against the bundled adapter's minimum supported version; badge the agent as misconfigured instead of letting it enter the retry loop.
Related
Summary
When the Claude CLI on the user's machine is incompatible with the bundled
claude-agent-acpadapter (in my case: CLI2.0.25does not support the--toolsflag that adapter0.60.0passes), everysession/newfails instantly. The adapter reports the precise cause in the JSON-RPC error'sdatafield:{"jsonrpc":"2.0","id":2,"error":{"code":-32603,"message":"Internal error", "data":{"details":"Claude Code process exited with code 1. stderr: error: unknown option '--tools'"}}}buzz-acpdiscardserror.datawhen constructingAcpError::AgentError(onlycodeandmessagesurvive —crates/buzz-acp/src/acp.rs:111-121), so the harness log and the user-facing channel notice both reduce to:Because
AgentErroris classified as an application-class error ("session is healthy — don't invalidate",crates/buzz-acp/src/pool.rs:2169; no respawn,handle_prompt_resultincrates/buzz-acp/src/lib.rs), the harness retries the hopeless spawn with backoff (10 attempts, 5s→300s) for every incoming message, dead-letters each batch, and never recovers or escalates. All managed agents on the machine (three in my case) wedge identically and indefinitely.The failure is deterministic and permanent, yet the user experience is an unexplained "Internal error" that looks transient. In my case it presented as "my agents died when I hit my Claude usage limit and never came back" — the actual trigger was that fresh CLI spawns resolved a different (older)
claudebinary than the still-running processes from the previous day, so everything kept working until the app restarted.Confirmed: upgrading the CLI (
npm install -g @anthropic-ai/claude-code@latest) and restarting the agents fully restores them — the version mismatch was the sole cause.Environment
xyz.block.buzz.app), three managed Claude agents@agentclientprotocol/claude-agent-acp0.60.0 (Buzznode-tools, bundled node v24.11.0)claude -psucceeds); does not support--toolsmain@aaf48fcReproduction
--toolsflag (e.g. 2.0.25) as theclaudethe login shell resolves.agent_returned (application error — pipe intact) … error=Agent reported error (code -32603): Internal error× 10 with backoff, thendead-lettering batch after 10 retries.error.data.details(probe transcript above).Root causes
acp.rsagent_error_from_jsonkeepscode+message, dropsdata. Per JSON-RPC 2.0,datais exactly where servers put the useful detail; the claude adapter uses it for the subprocess's stderr.AgentErrornever invalidates the session, never respawns, never trips the circuit breaker, and never varies its handling no matter how many consecutive identical failures occur — so a permanent config problem is retried forever as if transient.claude(nvm per-node-version globals make this easy) fails only at session-spawn time, with the message from (1).Suggested fixes
error.data(stringified, truncated) toAcpError::AgentError's Display and to theturn_errorobserver payload — one-line-ish change that would have made this self-diagnosing.AgentErrors per agent; after N identical failures, invalidate the session, then respawn the slot, then tripSlotCircuit— and surface a distinct user-facing notice ("agent failed N times with:Details
") instead of the generic retry text.claude --versionagainst the resolvedCLAUDE_CODE_EXECUTABLEand check it against the bundled adapter's minimum supported version; badge the agent as misconfigured instead of letting it enter the retry loop.Related