fix(google): cap contacts list pagination - #7
Conversation
gog contacts list followed nextPageToken with no page cap or repeated-token stop. A sticky or incrementing token hangs clawdex import google forever. Cap the walk at 50 pages and reject a repeated nextPageToken. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed August 15, 2026, 10:28 PM ET / August 16, 2026, 02:28 UTC. ClawSweeper reviewWhat this changesThis PR bounds Google contact pagination, rejects repeated continuation tokens, and adds regression coverage for token cycles and long page walks. Regression provenancePossible regression — suspected (reviewed change). No predecessor PR is attributed. Merge readinessKeep open for maintainer review: the patch fixes a source-proven infinite Google-import loop, but accepting a fixed 500-page ceiling is an intentional availability boundary for exceptionally large existing imports. Priority: P1 Review scores
Verification
How this fits togetherThe Google importer invokes the external flowchart LR
A[Google import command] --> B[Google contacts importer]
B --> C[gog contacts list]
C --> D[Contact page and token]
D --> E{Token empty, new, or repeated?}
E -->|new token| B
E -->|empty token| F[Local contact import]
E -->|repeated or limit reached| G[Import error]
Decision needed
Why: The code correctly prevents an unbounded external pagination walk, but the fixed ceiling deliberately changes behavior for unusually large existing accounts and is not derived from a documented Google maximum. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Retain cycle detection and a bounded paginator, with explicit maintainer acceptance that 500 pages is the intended operational limit for Google imports. Do we have a high-confidence way to reproduce the issue? Yes—the current-main loop has no termination guard beyond an empty token, and the PR supplies a concrete Is this the best way to solve the issue? Yes for the loop defect: token-cycle detection plus a bounded walk is a narrow solution; maintainer approval is still needed for the selected 500-page policy boundary. AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning high; reviewed against 7b533852b1fd. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (4 earlier review cycles)
|
Keep hang protection for a repeating or incrementing pager, but raise the safety ceiling to 500 pages so a valid 51-page listing still completes. Drop the release-owned changelog entry. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Pushed Also dropped the Unreleased changelog line (P3). @clawsweeper re-review |
Adjacent-duplicate checks miss A to B to A cycles. Track every non-empty continuation token and fail closed on the first repeat. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Pushed @clawsweeper re-review |
What Problem This Solves
clawdex import googlewalksgog contacts listby followingnextPageTokenwith no page cap and no cycle check. Ifgogor the People API keeps returning the same token, or a fresh token on every page, the import loops until the process is killed. The public command never returns.This is the same hang class as notcrawl#98 and babelfish#17: a pager that never empties
nextPageToken.Evidence
Public command against a local
gogstand-in on PATH (same argv as production:gog --no-input contacts list --json --max 1000). Built binary:/tmp/clawdex-pagecapfrom this branch.A sticky token still fails closed on the second page:
A finite two-page listing still imports Ada then Grace.
A valid listing that ends on page 51 now succeeds (Claw P1: do not reject a terminating walk past 50). An incrementing hang still stops at 500 pages (
--max 1000is 500_000 contacts, above a normal account).CHANGELOG.mdis left to the release process.Real behavior proof
Behavior or issue addressed:
clawdex import googleno longer followsnextPageTokenforever. A repeated token fails on the second page. Unique incrementing tokens fail at page 500. A listing that ends on page 51 still imports.Real environment tested: macOS (Darwin arm64), Go from the worktree at
/tmp/oc-impl-clawdex-pages, built./cmd/clawdexas/tmp/clawdex-pagecap, local contacts repo fromclawdex init.Exact steps or command run after this patch: Built
go build -o /tmp/clawdex-pagecap ./cmd/clawdex. Putgogstand-ins on PATH (repeat,increment,two-page,51-page). Ranclawdex --config ... --repo ... import google --account ada@example.com --dry-runfor the hang and two-page cases. Rango test -count=1 -race ./internal/googlefor the 51-page success and 500-page hang.Evidence after fix: terminal output from the patched binary and package run:
Observed result after fix: A sticky
nextPageTokenofsamestops after twogog contacts listcalls. Incrementingpage-Ntokens stop at 500 pages. A 51-page terminating listing returns 51 contacts instead ofexceeded 50 pages.What was not tested: A live Google People API account with a real sticky
nextPageToken. Avatar fetch during a capped walk.Summary
gog contacts listpagination at 500 pages.nextPageToken.ctx.Err()at the start of each page so a cancelled import stops between pages.Origin
The unbounded
for { nextPageToken }walk landed infc837601e11b(2026-05-08, Peter Steinberger) in the initial CLI bootstrap. Present for 99 days. Each page already usedCommandContext; the loop itself had no stop.Related
tools/listcursor.tools/listat 50 pages and rejects a repeated cursor.Verification
gofumpt/gofmtclean oninternal/google/gog.goandgog_test.go.go vet ./internal/googlego test -count=1 ./...go test -count=1 -race ./internal/googlego build -o /tmp/clawdex-pagecap ./cmd/clawdexclawdex import googleagainst the hang and two-pagegogstand-ins above.