block / block/buzz

[Bug] buzz-acp drops JSON-RPC error.data, hiding actionable failures — CLI/adapter version mismatch surfaces only as "-32603 Internal error" retry loops

Open
#2,422 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## 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:

```json
{"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

1. Install a Claude Code CLI version that predates the `--tools` flag (e.g. 2.0.25) as the `claude` the login shell resolves.
2. Run any managed Claude agent and mention it in a channel.
3. 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`.
4. 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

1. **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.
2. **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.
3. **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 `AgentError`s 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: ") 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

- [claude-agent-acp#338](https://github.com/agentclientprotocol/claude-agent-acp/issues/338) / [PR #363](https://github.com/agentclientprotocol/claude-agent-acp/pull/363) — adjacent adapter-side failure family (subprocess death → generic -32603; fixed upstream by returning -32002)
- #2265 — Claude agents fail silently when default model requires usage credits (same "silent wedge" experience, different trigger)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.