buzz-acp: channel wedges permanently when a session's agent child dies (-32603 retried into the same dead session until dead-letter)

Open Beginner friendly
#4,369 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
rust
Domain
backend

Research direction

Start in crates/buzz-acp/pool.rs at run_prompt_task and trace the AgentError handling, session cache lookup, and existing invalidate-and-recreate path used for max_turns_per_session rotation. Treat AgentError code -32603 as invalidating the session, then verify that a retry creates a fresh session instead of repeatedly prompting the dead one.

Written by the indexing model from the issue text.

Description

Draft: buzz-acp: channel wedges permanently when a session's agent child dies (-32603 retried into the same dead session until dead-letter)

Component: buzz-acp (crates/buzz-acp), observed at desktop-v0.5.3
Severity: channel outage until process restart, silent message loss

Summary

If a session's underlying agent child dies out-of-band (in our case: an operator killed claude session processes), the next session/prompt returns JSON-RPC -32603 "Internal error". buzz-acp classifies every AgentError as "application error — pipe intact", returns the agent to the pool, and crucially leaves SessionState.sessions[channel_id] pointing at the dead session:

  • pool.rs run_prompt_task error arm: if !matches!(e, AcpError::AgentError { .. }) { agent.state.invalidate(&source); } — the healthy-session exemption also covers dead sessions.
  • The requeued batch (MAX_RETRIES = 10, exponential backoff) re-enters run_prompt_task, hits the session cache (sessions.get(cid)), and re-prompts the same dead session every attempt until the batch dead-letters.
  • There is no per-session liveness probe and no session/load, so nothing ever heals the map short of restarting the whole process.

Real-world impact for us: two channels deaf for ~4 hours, 52 owner events dead-lettered.

Suggested fix (minimal)

Treat -32603 as session-invalidating: matches!(e, AcpError::AgentError { code, .. } if *code == -32603)agent.state.invalidate(&source). The already-existing requeue path then misses the session cache and create_session_and_apply_model builds a fresh session on the next attempt. False positives are cheap (one extra session/new); false negatives wedge the channel. The proactive max_turns_per_session rotation already proves the invalidate-and-recreate idiom.

We are running this patch locally and can PR it if you'd take it.

Dominant language
Rust
Stars
33.7k
Forks
4.4k
Avg merge
1d 21h
Merged PRs (30d)
239

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from block/buzz

All issues in block/buzz

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.