fix(paging): reject token cycles across CLI scans and backups - #1087
Conversation
Default gog docs comments list walks resolved-only pages by assigning pageToken = nextPageToken with no seen-set. A repeated Google token hangs until the process is killed. Track seen tokens and return pagination loop: repeated page token, matching collectAllPages. --all already used that helper; --locate already had its own seen map. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. Reviewed September 5, 2026, 5:34 PM ET / 21:34 UTC. ClawSweeper reviewWhat this changesAdds shared pagination-cycle detection across Google service scans and backups while preserving existing limits, early results, and ordinary API-error handling. Merge readiness✅ Ready for maintainer review Keep open: current main still needs this repair. The updated CLI traces resolve the prior proof blocker, the changelog finding is fixed, and no actionable correctness findings remain. Priority: P2 Review scores
Verification
How this fits togethergog’s scan helpers collect paginated Google API results for reports, message and contact operations, and encrypted backups. They must finish successfully before callers publish complete results or perform dependent actions. flowchart TD
A[CLI command] --> B[Google API page request]
B --> C[Rows and continuation token]
C --> D{Continue scanning?}
D -->|Finished or limit reached| E[Report, action, or backup]
D -->|More pages| F{Token already used?}
F -->|No| B
F -->|Yes| G[Existing error handling]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Technical reviewBest possible solution: Use the shared cycle guard while retaining each caller’s established completion, capacity, and error contracts. Do we have a high-confidence way to reproduce the issue? Yes: current source exposes unguarded repeated-token loops, and the supplied main-control trace demonstrates repeated Docs requests. This read-only review did not execute the CLI. Is this the best way to solve the issue? Yes: sharing cycle detection while preserving bounded and unbounded scan contracts is a narrow repair, supported by caller-level regressions and stock-CLI fault traces. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 25703c789da5. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
History |
Consolidate the repeated-token fixes from openclaw#1078 through openclaw#1087 using a shared cycle guard. Preserve unlimited distinct-page scans, early matches, and previously fetched ACL/member rows on ordinary API errors. Add generated-client regression coverage, stock-binary HTTPS fault proof, and credited release notes. Co-authored-by: Sebastien Tardif <SebTardif@ncf.ca>
|
Maintainer proof for
The nine sibling pagination PRs are incorporated here with @SebTardif credited. They should be closed as superseded only after this PR lands. No merge or issue closure was performed in this preparation session. Exact-head CI passed on Linux, Windows, and macOS, plus the tracking worker: https://github.com/openclaw/gogcli/actions/runs/33991525608 Captured stock-binary fault-injection outputThe fixture launches the unmodified CLI with an isolated home, a synthetic direct token, and a local HTTPS proxy/CA. It records requests and downstream writes; backup cases initialize a disposable encrypted repository, seed it, inject the fault, then verify the manifest/Git HEAD or decrypt the affected shard. Build and run entry points: go build -o "$TMPDIR/gog-paging" ./cmd/gog
python3 paging-cli-proof.py "$TMPDIR/gog-paging" docs docs-open tree inventory du dedupe dedupe-limit gmail calendar calendar-match drive-drives drive-files calendar-list calendar-events calendar-settings contacts other-contacts contact-groups task-lists tasks groups admin-users admin-groups keep workspace forms permissions comments revisions acl acl-ordinary members members-ordinaryMain control (same synthetic peer, bounded by a fixture safety cap): {
"case": "docs",
"expect": "old",
"exit": 1,
"requests": [
{
"method": "GET",
"path": "/drive/v3/files/fixture-document/comments",
"page": ""
},
{
"method": "GET",
"path": "/drive/v3/files/fixture-document/comments",
"page": "stuck"
},
{
"method": "GET",
"path": "/drive/v3/files/fixture-document/comments",
"page": "stuck"
},
{
"method": "GET",
"path": "/drive/v3/files/fixture-document/comments",
"page": "stuck"
}
],
"writes": [],
"stdout": "",
"stderr": "Note: Using direct access token (expires in ~1 hour; no auto-refresh)\nGoogle API error (400): fixture stopped unguarded paging\n"
}Candidate output: |
Repeated Google page tokens could leave backups, Drive reports, contact dedupe, Gmail bulk queries, recurring Calendar lookups, and open-comment scans running indefinitely. This consolidates #1078–#1086 into this existing contributor PR and gives those paths one shared cycle guard.
The repair preserves each caller's behavior: existing unlimited scans stay unlimited, bounded scans and occurrence lookup stop as soon as satisfied, and ordinary later-page ACL/membership errors retain previously fetched rows. Cycles discard the affected incomplete collection and follow the existing command or backup error path. The existing bounded all-pages collector keeps its 10,000-page limit.
Validation includes generated-client regressions, the local CI gate, and 33 real built-CLI runs against a local HTTPS fault-injection peer. Those runs cover repeated-token errors, zero downstream writes after failed scans, early-result success, unchanged existing backup manifests/Git HEAD after fatal collection errors, and decryption of embedded error rows and retained ACL/membership records. All inputs, credentials, and resources in the fault fixture are synthetic; this does not claim that a healthy Google endpoint was forced to emit a bad cursor.
Credited Unreleased entries and command/backup documentation are included. The nine sibling PRs remain open for maintainer closeout after this consolidated repair lands. This does not resolve #1059's Cloud Identity query validation or change Gmail-web MIME behavior or download defaults.
Co-authored contribution: Sebastien Tardif (@SebTardif); preserved in the commit credit.
Captured examples from the stock-binary run (synthetic HTTPS peer):
Full request-count and backup-result trace.