Skip to content

fix(provider): overhaul openai-subscription retry policy - #32

Merged
danielkov merged 1 commit into
mainfrom
retry-policy-overhaul
Aug 27, 2026
Merged

fix(provider): overhaul openai-subscription retry policy#32
danielkov merged 1 commit into
mainfrom
retry-policy-overhaul

Conversation

@danielkov

Copy link
Copy Markdown
Contributor

Problem

A turn died on the first response.failed carrying service_unavailable_error/server_is_overloaded: retriability for statusless SSE errors was an exact-match allowlist, and neither the _error-suffixed type nor the server_is_overloaded spelling was on it.

Changes

Classification flipped to default-retry. Statusless errors now retry unless excluded: auth errors (401/403 or auth-shaped codes) and permanent errors (status list plus substring markers: billing, content_policy, deactivated, insufficient, invalid, not_found, not_supported, permission, quota, unsupported). Unknown transient spellings can no longer kill a turn.

Retry budget 10m → 24h, time-driven only (MAX_RETRIES removed). Backoff cap 30s → 60s, jitter schedule unchanged. A 10m per-attempt guard (ATTEMPT_TIMEOUT) covers send/credential/first-event operations the stream idle timeout can't; attempt timeouts retry within the budget rather than failing fatally.

Rate-limit resets respected. On 429, x-ratelimit-reset-* headers (max across headers; plain seconds, unit durations like 6m30s, epoch s/ms) win over Retry-After. The deadline becomes reset + 10m grace, clamped to the 24h ceiling, with waits paced at most 10m apart. Reset headers on non-429 statuses are ignored (they're quota metadata on every response). All server delay hints are capped at 10m so a bogus Retry-After can't stall a turn.

reopen_stream keeps request_context in place across its awaits instead of taking it, so a reopen cancelled by the first-event timeout stays retryable instead of failing with stream retry context is unavailable.

Statusless errors like service_unavailable_error/server_is_overloaded
failed fatally because retriability was an exact-match allowlist.
Classification now defaults to retrying and excludes permanent errors
by heuristic instead.

- retry budget 10m -> 24h, time-driven only (MAX_RETRIES removed)
- backoff cap 30s -> 60s; per-attempt 10m guard on send/credentials
- honor x-ratelimit-reset-* on 429 over Retry-After: pace waits at
  10m and retry until reset + 10m grace, clamped to the 24h budget
- cap all server delay hints at 10m
- reopen_stream keeps request_context in place so a cancelled reopen
  stays retryable from the first-event timeout path
@danielkov
danielkov merged commit f59e203 into main Aug 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant