Skip to content

fix: Stop the paginator when a page cursor repeats - #641

Merged
razor-x merged 1 commit into
mainfrom
claude/python-sdk-audit-o2iid9-08-cursor-guard
Aug 28, 2026
Merged

fix: Stop the paginator when a page cursor repeats#641
razor-x merged 1 commit into
mainfrom
claude/python-sdk-audit-o2iid9-08-cursor-guard

Conversation

@razor-x

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

Copy link
Copy Markdown
Member

What

Neither paginator had any loop guard: a server regression or proxy-cached page that repeats a next_page_cursor looped flatten() forever and grew flatten_to_list() until OOM — the per-request timeout resets every page, so nothing else stops the process (SDK audit finding M6; ports JS #1006 / PHP #466).

  • Page traversal, previously duplicated across four loops (flatten / flatten_to_list × sync / async), is centralized in one private _walk() generator per paginator — the same single-walker shape as the JS fix, so the guard cannot be missing from one of the copies.
  • _walk() keeps a seen-cursor set and stops silently when the server hands back a cursor it has already followed.

Stacked on #640; diff shrinks as the stack merges.

Testing

New tests (sync flatten_to_list, sync flatten, async) against a recording server that pins one cursor: the paginator fetches the first page, follows the cursor once, sees it repeat, and stops — request count pinned at exactly 2, per the JS-wave lesson that loop-guard tests must count requests, not just observe termination.

Revert check: with the previous paginator restored, the test loops until killed by a 15s timeout — the audit's infinite-loop symptom.

Full suite: 235 passed; mypy, pylint (10.00), black clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y1RzepycXEYA3LStfjt8cY


Generated by Claude Code

@razor-x
razor-x requested a review from a team as a code owner August 27, 2026 21:42
@razor-x
razor-x changed the base branch from main to claude/python-sdk-audit-o2iid9-07-paginator-hooks August 28, 2026 00:15
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from 88e0597 to 200d836 Compare August 28, 2026 19:30
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from 200d836 to eee59af Compare August 28, 2026 20:36
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from eee59af to 03dbf13 Compare August 28, 2026 20:43
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from 03dbf13 to 89281e3 Compare August 28, 2026 21:04
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from 89281e3 to 93db652 Compare August 28, 2026 21:09
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from 93db652 to 28f700c Compare August 28, 2026 21:12
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from 28f700c to d1d8c62 Compare August 28, 2026 21:17
Base automatically changed from claude/python-sdk-audit-o2iid9-07-paginator-hooks to main August 28, 2026 21:23
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y1RzepycXEYA3LStfjt8cY
@razor-x
razor-x force-pushed the claude/python-sdk-audit-o2iid9-08-cursor-guard branch from d1d8c62 to c5f8974 Compare August 28, 2026 21:29
@razor-x
razor-x merged commit 840b499 into main Aug 28, 2026
23 checks passed
@razor-x
razor-x deleted the claude/python-sdk-audit-o2iid9-08-cursor-guard branch August 28, 2026 21:40
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