fix(retry): cap backoff exponent to avoid OverflowError on large attempts - #1761
Open
winklemad wants to merge 1 commit into
Open
fix(retry): cap backoff exponent to avoid OverflowError on large attempts#1761winklemad wants to merge 1 commit into
winklemad wants to merge 1 commit into
Conversation
…mpts
`backoff()` returned `min(cap, base ** attempt)`. Because `base` is the float
`2.0`, `2.0 ** attempt` overflows a C double at `attempt >= 1024` and raises
`OverflowError` before `min()` can clamp it, so the documented cap is never
returned -- the environments poller (the only caller) then dies with an
uncaught error instead of continuing to retry at the cap.
Cap the exponent at 1000, mirroring the guard `_base_client` already applies
("Also cap retry count to 1000 to avoid any potential overflows with `pow`").
The returned value is unchanged for every attempt (once `base ** attempt`
reaches `cap` the result is always `cap`); only the crash is removed. Extended
the existing `test_backoff` with the overflow-boundary cases.
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.
Fixes #1760.
Problem
anthropic.lib._retry.backoff(attempt, *, cap, base=2.0)returnsmin(cap, base ** attempt). Becausebaseis the float2.0,2.0 ** attemptoverflows a C double atattempt >= 1024and raisesOverflowErrorbeforemin()can clamp it, so the documented cap is never returned:The only caller is the environments poller (
lib/environments/_poller.py,_backoff = backoff(attempt, cap=60.0)). Its counter resets to 0 on success, so this needs ~1024 consecutive transient failures — but at that point the run-forever poll loop dies with an uncaughtOverflowErrorinstead of continuing to retry at the cap.Fix
Cap the exponent at 1000, mirroring the guard the core client already applies in
_base_client.py:backoff()just missed the same guard. The returned value is unchanged for every attempt — oncebase ** attemptreachescapthe result is alwayscap, which happens far belowattempt = 1000— so this only removes the crash.Tests
Extended the existing
test_backoff(tests/lib/environments/test_poller.py) with the overflow-boundary cases (attempt=1024andattempt=5000, both expecting the60.0cap). They raiseOverflowErrorbefore this change and pass after; the existing cases are unchanged.Verified locally with
ruff check/ruff formatclean.