Provider retry
The plugin is enabled on fresh installations. It reacts only to failed Codex
and Claude Code turns and never blocks a send; prior output or tool activity
does not prevent a retry. It queues a retry of the failed turn, which core
runs by continuing accepted input or re-sending input the provider never
accepted, for one of three failures:
- A structured provider overload: retried after a short delay that doubles on
each attempt.
- An unavailable provider (HTTP 500, 502, 503, or 504, an internal error, or a
failed or dropped connection, including an Account Pooler that could not
reach the provider): retried after about a minute, doubling on each attempt.
- A subscription-window limit with a reported reset time: retried shortly
after the window opens, with random spread so threads on one account do not
wake together. Credit and spend limits are not retried.
For Account Pooler routes, retry timing comes from the pool's earliest usable
account for the failed request's model, including parent pools, so a generic
provider 429 without quota windows can still schedule a retry. Unknown resets,
authentication failures, and unavailable pool sources do not schedule retries.
A turn gets at most four automatic retries. The maximumWait setting
(6 hours by default, or 24 hours or No limit) skips a subscription-limit
retry whose reset is farther away:
bb plugin config provider-retry set maximumWait "24 hours".
A pending retry is an ordinary durable queued row, shown on the thread's queue
card with its reason and time, and survives restart.
bb provider-retry status [thread-id] [--json]
bb provider-retry explain [thread-id] [--json]
bb provider-retry retry <thread-id> [--json]
bb provider-retry cancel <thread-id> [--json]
status defaults to the current thread and lists every thread outside one.
explain reports the last recorded scheduling or skip decision; it is
historical and survives restart, so use status for what is still pending.
Decisions from before the plugin version that records them are not
backfilled. The plugin RPC decision.get accepts { threadId } and returns
the same nullable diagnostic.
retry sends the pending row now; cancel deletes it. Inspect the failed turn
before retrying manually, and avoid duplicating an existing queued retry. Use
the core bb thread retry command for an intentional manual retry of a turn
with no pending row; follow its live help for selection and scheduling flags.