Skip to content

fix: Stop polling an action attempt once the timeout passes - #635

Open
razor-x wants to merge 2 commits into
mainfrom
claude/python-sdk-audit-o2iid9-02-poll-deadline
Open

fix: Stop polling an action attempt once the timeout passes#635
razor-x wants to merge 2 commits into
mainfrom
claude/python-sdk-audit-o2iid9-02-poll-deadline

Conversation

@razor-x

@razor-x razor-x commented Aug 27, 2026

Copy link
Copy Markdown
Member

What

Rewrites poll_until_ready / poll_until_ready_async around a monotonic deadline (SDK audit finding H2; ports the JS #1004 / PHP #465 fix):

  • Validate options up front: timeout < 0 and polling_interval <= 0 (including NaN) raise SeamInvalidOptionsError with the same messages as the JS SDK, instead of looping forever or leaking a ValueError out of time.sleep.
  • Deadline instead of an accumulator: the old loop advanced its clock only by polling_interval, so polling_interval=0 never timed out (audit reproduced 1,915 unthrottled polls in 3s) and HTTP round-trip time was excluded entirely — a "5 second" timeout could block for minutes.
  • Sleep-then-check with min(polling_interval, remaining): the wait no longer overruns its timeout by a full interval (timeout=0.5, polling_interval=5 previously slept 5s), and it always polls at least once even when timeout < polling_interval.
  • Check the attempt already in hand first: resolve_action_attempt now seeds the poll with the attempt it just received, so an already-resolved attempt no longer costs an extra /action_attempts/get round trip (same as JS/PHP).

Both the sync and async variants carried identical bugs; both are fixed identically.

Testing

New tests (sync + async, pinned messages): zero and negative polling_interval raise, negative timeout raises, a timeout < polling_interval wait still polls exactly once (request-count asserted via a recording server) and finishes near the deadline. The existing interval-overrun test now asserts elapsed time, which it previously did not.

Verified per the audit-fix recipe: with seam/modules/action_attempts.py reverted to main, the new tests fail with the audit's exact symptoms (5s sleep on a 0.5s timeout; a negative timeout surfacing as SeamActionAttemptTimeoutError: Timed out ... after -1s).

Full suite: 191 passed. mypy, pylint (10.00), black all clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y1RzepycXEYA3LStfjt8cY


Generated by Claude Code

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.

2 participants