fix(opencode): stop retrying when the provider asks to wait for hours - #47641
fix(opencode): stop retrying when the provider asks to wait for hours#47641ApexMene wants to merge 3 commits into
Conversation
delay() honors retry-after up to RETRY_MAX_DELAY (~24.8 days), so an exhausted quota window parks the session on a single attempt that can be a full day out. Give up past RETRY_MAX_WAIT instead, after publishing the retry status so the limit dialog still fires.
|
The following comment was made by an LLM, it may be inaccurate: Found 2 potentially related PRs:
These PRs appear to address related concerns around stopping long waits during rate limiting and quota exhaustion scenarios. PR #47339 in particular seems closely aligned with the current PR's goals around free tier and Go limit handling. |
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
|
Thanks for the thorough review! Applied both non-blocking notes in f258440:
Verified with |
Issue for this PR
Closes #39790
Type of change
What does this PR do?
SessionRetry.delay()returns whatever the provider puts inretry-after, capped only byRETRY_MAX_DELAY(~24.8 days).policy()then schedules the next attempt that far out, so an exhausted quota window parks the session on one pending attempt that can be a full day away. Nothing is logged after the firststream error, nosession.erroris published, and the session never reaches idle.zen is one concrete source:
getRetryAfterDay()inpackages/console/app/src/routes/zen/util/ipRateLimiter.tssetsretry-afterto the seconds left until the next daily reset, so an exhausted free tier can answer with up to 86400.The change stops the schedule when the requested wait is longer than
RETRY_MAX_WAIT(5 minutes). The retry status is published first, so the free tier and Go limit dialogs fire exactly as they do today, thenCause.donelets the error reachhaltin the processor and the session goes idle. Waits inside the ceiling are untouched, so normal 429 and 5xx backoff behaves as before.How this relates to the other open PRs on the issue, since the duplicate bot flagged them:
free_tier_limitandaccount_rate_limitreasons, which are derived from zen specific markers in the response body. That covers zen, but a provider that just answers with a longretry-afterand no recognizable body still hangs the same way. This PR gates on the wait itself, so it covers that case too. The two are not exclusive, they compose fine if you want both.runfrom sleeping through an exhausted quota #42340 fixes the reporting side inrunand is independent of this.I hit this through a subagent, which is where it hurts most: the retry status is published on the child session ID, and both the TUI and the app ignore
session.statusfor sessions other than the routed one, so the parent turn shows a spinning task tool and no dialog at all. Two of my sessions sat like that for 9h26m and 8h52m before I noticed.How did you verify your code works?
Free tier actually exhausted, isolated
XDG_DATA_HOME, same command both times:timeout 120Error: Rate limit exceeded. Please try again later., exit 1, 3.8sTwo new tests in
packages/opencode/test/session/retry.test.ts, one per side of the ceiling. The first one fails ondevand passes with the change.bun test test/session/gives 415 pass andbun typecheckis clean, both run frompackages/opencode.Screenshots / recordings
Not a UI change.
Checklist