Repository navigation
acpmux: a 503/529 capacity error retries the turn in the same session, and the session row shows the wait - #25232
Conversation
…ow shows it (red) Unit tests for the 503 'no non-exhausted accounts', 529 overloaded_error and 'at capacity' texts, and an integration test with the fake agent's cap-fail-once prompt: the turn continues in the same session and the session row carries retry while it waits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ws the wait
A turn that fails on HTTP 503 or 529, overloaded_error, the SR2 gateway's
'no non-exhausted ... accounts' or 'at capacity' now goes through auto_resume
(reason capacity) instead of the fallback profile or nothing. turn_errors gains
transient_cause, the classifier the subagent retry shares. Status codes match
as whole numbers, so the gateway's port 4016 no longer reads as a 401.
The session row gets retry {attempt, of, reason, nextAt, promptId, turnId},
null when nothing waits; auto_resume_scheduled gains of, reason and nextAt,
auto_resume_exhausted gains reason, and watchers hear all three. Stop, close
or a turn that took the chat wake the wait at once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Owned by hb-acpmux on big-red · session |
|
Found 10 test failures on Blacksmith runners: Failures
|
|
Bead |
…-less overload is a route failure (red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… row; overloads stay route failures Review round 1 (Codex): a 400/403/404/413/422 or invalid_request_error, permission_error, a rejected tool use wins over transient words in the same text (is_refused_request). An attempt refused before its turn starts records auto_resume_skipped 'refused' with its error, so watchers see retry go. The route-failure predicate (now is_route_failure) counts capacity errors with or without their status, so a bound route's diagnostics, probe and autoFallback still see a status-less overloaded_error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d (red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2 (Codex): resume_cause checks is_refused_request on the raw and the shown error before the agent_exited shortcut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Gallery before/after for
States
Pick other states with a red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 0fd73db to compare; do not merge until green; see lane-rules |
|
Shipped in:
|
…/off, seconds between tries, tries per error) (#31709) Lawrence via Leo (ask-082cdbe456): "should have retry button + configurable timer loop retry". The error card's Retry has led capacity failures since 9e836df; acpmux already retries rate limits, capacity and lost connections on its own (#25232, #27924), but only its config.json could change the loop. agents.autoRetry.{enabled,intervalSeconds,attempts} in the settings file now set it, read at each retry; config.json's autoResumeDelaysMs still comes first. Agent-Session: https://cmux.com/deeplink/agent?id=aid-5224b647da981c2d3c39 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo, word for word (2026-10-26): "this needs to retry :("
subsession-card's ask, daemon half (a): "A turn that fails on a transient upstream error (HTTP 503, 529 overloaded, "no non-exhausted ... accounts", "overloaded_error", or a connection reset or EOF to the gateway) retries by itself with backoff, then gives up. It resumes the same session and turn, never a new session. Emit a state on the session or turn that the webview can draw. Non-transient errors (auth, a bad request, a refused permission) never retry."
Why these turns never came back
hub/turn_errors.rsread every one of them as an account limit, soresume_causereturned nothing and the turn sat failed:is_limit_errormatched any401in the text. The SR2 gateway's errors name its port,(127.0.0.1:4016)/sr2-gateway…:4016, so every SR2 error read as a sign-in failure. That includes the 503 "no non-exhausted claude accounts" error and a plainECONNRESETto the gateway.is_limit_erroralso matchedoverloaded, so a 529overloaded_errorand Codex's "Selected model is at capacity. overloaded" went to the fallback-profile path, or to nothing when there was no fallback.What changed (PR 1 of 2;
_acpmux/retryis PR 2)turn_errors: newis_capacity_error(HTTP 503 or 529,overloaded, "at capacity", "no non-exhausted … accounts") andpub fn transient_cause(error) -> Option<&'static str>. It returnscapacity,transport, orNonefor limits, sign-in and anything else. hb-retry-subagent shares this classifier.resume_causecalls it and keeps its ownagent_exitedbranch. Status codes (401,429,503,529) now match only as whole numbers.overloadedis no longer a limit. Transport also coversunexpected eofandearly eof.auto_resume: capacity errors go through the existing continuation path in the same session (prompt idP~resume-n, the harness's own resume), with a continuation text that names the capacity error.session/list_meta.acpmux,_acpmux/sessions,_acpmux/session_changed):retry: {attempt, of, reason, nextAt, promptId, turnId}, wherereasoniscapacity|transport|agent_exitedandnextAtis epoch ms. It is null when nothing waits, and it clears when the attempt fires, is skipped (Stop, close, a turn that took the chat) or runs out. New protocol typesRetrySummaryandRetryReason. The IR and the webview's generated types are regenerated.auto_resume_scheduledgainsof,reasonandnextAt.auto_resume_exhaustedgainsreason. Watchers now hear all threeauto_resume_*records as_acpmux/session_changed, so the row'sretrycomes and goes live.Field names match hb-acpmux's contract (
retry-contract.md).subagentId?on the row is hb-retry-subagent's to add.Decisions
Stop conditions (timers)
The one timer is each chat's existing auto-resume wait. It now ends at its delay or when its mark is dropped (
Wake'sDropnotifies it): Stop, close, a newer turn taking the chat, or the attempts running out. In every case the task then records the skip or fires once and exits. No new observer or loop.Tests (red first)
turn_errors::capacity_errors_are_continued_in_placeanda_dropped_gateway_connection_is_continuedfailed (anECONNRESETnaming the gateway's:4016read as a 401). So did the integration testsauto_resume::capacity::*("never scheduled") and thereasonassertion added toautomatic_continuations_stop_after_the_configured_attempts.overloaded_errorJSON and "Selected model is at capacity." arecapacity. 429 / "hit your limit" / usage limit / 401 / "Not logged in" / invalid API key / 400invalid_request_error/ permission refusals stayNone.cap-fail-once:answers with the SR2 503): the turn continues in the same session with the same agent session id and prompt idp-cap~resume-1. While it waits,retryshows inhub.session_summary, insession/listand in_acpmux/sessions. It is null after the attempt fires. Stop clears it at once, and a watcher hearsauto_resume_scheduledwithretryand thenauto_resume_skippedwithretry: null. A prompt sent meanwhile clears the row, and the wait is skipped assuperseded.cargo fmt -p acpmuxmakes no diff;cargo test -p acpmux --libpasses 813 tests,protocol_ir_is_currentamong them;--test hub_integrationpasses 411;clippy --all-targetsis clean. The webview'sbun run acpmux-protocol:checkis current (run 40253470646).Review
Codex gpt-6-astra (xhigh) review: SHIP at 98178f2 after three rounds (round 1: a refused attempt vanished without a watcher event, bad requests could retry through EOF words, status-less overloads lost route fallback; round 2: the agent_exited shortcut bypassed the refusal guard; each fixed red-then-green).
No capture: no UI changes here. The webview lane draws
retryfrom these fields.Compatible with #23921 (restart continuations): it reuses
split_attempt,SUFFIXandMAX_ATTEMPTSunchanged, and this PR leaves the doc lines that PR edits untouched.Agent session: big-red
🤖 Generated with Claude Code