Bedrock 429 handling is inconsistent for parallel subagents: pre-flight rejection kills the agent, mid-stream failure silently switches it to the ANTHROPIC_MODEL fallback
What's Wrong?
Running a Workflow with ~8 parallel subagents (high effort, each reading many files) on Bedrock exhausts the tokens-per-minute quota. The resulting failures take two different code paths with very different outcomes, and one of them silently changes the model mid-agent:
- Pre-flight rejection — Bedrock refuses the request at the quota gate with
API Error: Request rejected (429) · Too many tokens, please wait before trying again.The subagent dies terminally on that turn (recorded as anisApiErrorMessageturn with"model":"<synthetic>"). No in-place retry, no backoff, no fallback — even though the error message literally says "please wait before trying again". The orchestration layer then has to re-spawn the whole agent from scratch (losing all its progress/context).
- Mid-stream failure — a request that was accepted but whose stream broke (observed as an assistant turn with an empty/aborted thinking block, zero error events in the transcript). This goes through the internal stream-retry path, which silently re-issued the turn on the model pinned in
ANTHROPIC_MODEL(us.anthropic.claude-opus-4-8[1m]in my env) instead of the session/agent model (claude-fable-5). The agent then continued on Opus for the rest of its run. Nothing was surfaced — the only indications are the per-turn"model"fields in the transcript JSONL and the model badge in the/workflowsTUI flipping to "Opus 4.8".
Why this matters
- Asymmetry: the failure mode that could be retried cheaply (pre-flight 429, no tokens consumed) is terminal, while the one that got a partial response silently degrades/changes the model. Intuitively it should be the other way around, or at least consistent.
- Silent model switch: for workflows that depend on a specific model (evaluation runs, model comparisons, cost control), a subagent quietly switching from the session model to the env-pinned fallback mid-conversation invalidates the run with no warning. At minimum this deserves a visible notice/log line, ideally an opt-out.
- Wasted work: terminal 429 death discards the agent's whole context; a re-spawned agent re-reads everything (more tokens → more quota pressure → more 429s — the failure amplifies itself).
Evidence (from workflow transcript JSONL)
Timeline: 9 subagents started simultaneously at 16:51:20; two died on hard 429s 4–5 min in; every agent started after the burst subsided completed clean; one late agent hit the mid-stream failure and switched models:
16:51:20 9 finder agents start in parallel
16:55:43 agent A dies: {"isApiErrorMessage":true, model:"<synthetic>",
content:"API Error: Request rejected (429) · Too many tokens, please wait before trying again."}
16:56:08 agent B dies: same terminal 429
...
17:43:55 agent C starts (re-spawn of a died dimension)
17:54:2x agent C: fable-5 turn with empty/aborted thinking block (no error event),
immediately followed by the same turn re-emitted with "model":"claude-opus-4-8";
continues on Opus for the remaining ~9 turns
Dead-agent transcript tail (turn-level view):
ok claude-fable-5
ok claude-fable-5
ERR <synthetic> API Error: Request rejected (429) · Too many tokens, please wait before trying again.
<end of transcript — agent dead>
Fallback-agent transcript around the switch (line numbers from the JSONL):
line 54 user tool_result (file read)
line 55 assistant model=claude-fable-5 thinking block empty/aborted, no error flag
line 56 assistant model=claude-opus-4-8 same turn re-emitted; all subsequent turns on Opus
Expected Behavior
- Pre-flight 429s ("please wait before trying again") should get bounded backoff-and-retry on the same model before the turn is declared terminal, matching how mid-stream failures are retried.
- If a fallback to
ANTHROPIC_MODEL(or any model other than the one the agent was launched with) happens, surface it: a system line in the transcript, a notice in the workflow/agents UI, or at least a structured log event — and ideally a setting to disable cross-model fallback for consistency-sensitive runs.
Related issues (adjacent, not duplicates)
- #68816 — rate-limit/usage-limit is recorded as a synthetic assistant turn with terminal
stop_reason: stop_sequence, indistinguishable from a clean completion. That's the transcript-representation side of failure mode 1 here (why orchestration sees the agent as "done" rather than "parked"). - #64328 — workflow harness retry behavior on 429 without backoff/circuit-breaker, amplifying token burn. That's the orchestration-layer amplification of failure mode 1 (each respawned agent re-reads everything under an already-exhausted quota).
Neither covers the silent cross-model fallback on mid-stream failure (failure mode 2), which is the main new report here; filing separately per the one-bug-per-issue guideline but linking for triage.
Environment
- Claude Code 2.1.215, macOS (Darwin 25.5.0)
- Provider: Bedrock (
CLAUDE_CODE_USE_BEDROCK=1,AWS_REGION=us-east-1) - Session model:
us.anthropic.claude-fable-5; env:ANTHROPIC_MODEL=us.anthropic.claude-opus-4-8[1m] - Repro context: Workflow tool with 8 parallel high-effort subagents doing code review over a ~10k-line repo; concurrency cap 10 (12-core machine)
Is this a regression?
Unknown — first time running this many high-effort parallel subagents on this account/quota.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗