fix(session): stop retrying when the provider reports an exhausted budget - #47686
Open
CannonRS wants to merge 1 commit into
Open
fix(session): stop retrying when the provider reports an exhausted budget#47686CannonRS wants to merge 1 commit into
CannonRS wants to merge 1 commit into
Conversation
…dget A provider can report an exhausted budget without asking for a long wait and without any recognisable phrase in the message. `retryable` only looks at prose, so those responses run the full five attempts and the session waits for a limit that resets on a billing or daily window. Classify the documented structural signals instead: HTTP 402, the OpenAI billing error codes, and a google QuotaFailure whose quota id names a per-day window. Those end the schedule after the retry status is published, so the UI still reports the limit and the error then reaches the caller. Per-minute quotas, plain 429s and everything else keep their current retry behavior.
Contributor
|
The following comment was made by an LLM, it may be inaccurate: Related PRs Found:
Context: The PR description explicitly states these three PRs are complementary and compose together:
These are not duplicates — they address different aspects of the retry classification problem and all three are meant to work together. The PR description confirms none subsumes another. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #47685
Type of change
What does this PR do?
retryable()decides whether a provider error is worth another attempt by looking at prose — themessage and the response body run through
RETRYABLE_MESSAGE_PATTERNS, plus two zen-specificmarkers. A provider that reports an exhausted budget without a recognisable phrase, and without
asking for a long
retry-after, falls through as an ordinary retryable error. The session thenspends all five attempts on a limit that resets on a billing or daily window.
This classifies the documented structural signals instead of the wording:
insufficient_quota,billing_hard_limit_reached,billing_not_active,account_deactivated), read fromerror.type/error.codeor thetop-level
code/type,QuotaFailurewhosequotaId/quotaMetricnames a per-day window.These are stable identifiers rather than message text, which varies per provider and locale.
A terminal result ends the schedule, but only after the retry status has been published, so the UI
reports the limit exactly as it does today and the error then reaches the caller instead of a
pending attempt. Per-minute quotas, plain 429s, 5xx and everything else keep their current retry
behavior — the new checks run after the existing classification and only add a
terminalflag.Relation to the other open PRs in this area, since they overlap in this file: #47339 stops on
the
free_tier_limitandaccount_rate_limitreasons, which are derived from zen markers in thebody; #47641 stops when the requested wait exceeds a ceiling. This PR covers the case neither
reaches — a structural budget signal with a short or absent
retry-afterand no zen marker. Allthree compose; none of them subsumes another.
How did you verify your code works?
Five new tests in
packages/opencode/test/session/retry.test.ts, additive — no existingexpectation was changed:
insufficient_quotabody is terminal,QuotaFailureis terminal,QuotaFailurestays retryable,Verified the three terminal cases fail on unmodified
devand pass with the change.bun test test/session/retry.test.tsinpackages/opencode: 65 pass, 0 failtsgo --noEmitinpackages/opencode: cleanprettier --checkon both changed files: cleanoxlinton the changed file: 2 warnings, the same two present ondevbefore this changeNot verified: an exhausted account against a live provider. The classification is driven by the
documented response shapes, and the tests use those shapes verbatim.
Screenshots / recordings
Not a UI change.
Checklist