fix(api): stop Slack pagination on a repeated cursor - #159
Conversation
conversations.list, channel history, thread replies, and DM listing followed next_cursor forever when Slack repeated the token. Reject a repeated cursor the same way MCP tools/list already does. 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 29, 2026, 3:57 AM ET / 07:57 UTC. ClawSweeper reviewWhat this changesThe PR stops Slack channel, history, thread-reply, and DM pagination when a cursor repeats, with four regression tests. Merge readinessKeep this PR open: current main still lacks repeated-cursor guards, while the introduced implementation is a focused, correct fix with production-client HTTP regression coverage. Priority: P2 Review scores
Verification
How this fits togetherSlacrawl’s Slack sync client pages conversations and messages before storing them in the local archive. Cursor handling determines whether a sync proceeds through pages or terminates with an error. flowchart LR
A[Slack API pages] --> B[Slack sync client]
B --> C[Pagination cursor]
C --> D{New or repeated?}
D -->|New| E[Next Slack request]
D -->|Repeated| F[Return sync error]
E --> G[Local archive]
Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Rebase onto current main and land the four guards with their focused regression coverage, retaining the established MCP-style repeated-cursor error behavior. Do we have a high-confidence way to reproduce the issue? Yes—source establishes a deterministic reproduction: return the same non-empty Slack cursor twice through the production client, as each of the four checked-in HTTP tests does. Is this the best way to solve the issue? Yes—the patch mirrors the repository’s existing MCP cursor-cycle guard and preserves normal empty and newly advancing cursor behavior. AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning high; reviewed against dcbc12d44837. LabelsLabel changes:
Label 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 (19 earlier review cycles; latest 8 shown)
|
|
Maintainer triage: recommend LAND with the test/docs follow-up on I reproduced all four loops with the real built CLI and a local TLS proxy returning synthetic Slack responses. Current main kept following the repeated cursor until interrupted (102 channel-list requests, 14 history requests, 15 reply requests, 122 DM-list requests in this run). This PR returned a method-specific Commands: GOWORK=off go build -o /tmp/slacrawl-main ./cmd/slacrawl # main
GOWORK=off go build -o /tmp/slacrawl-159 ./cmd/slacrawl # PR head
python3 proof159.py /tmp/slacrawl-main /tmp/slacrawl-159The harness runs each binary as The original history and reply regression tests also failed locally before reaching pagination: their 300 ms deadline included SQLite fixture setup. The support commit starts the deadline after setup, allows five seconds for the operation, and retains the exact two-request assertion. It includes docs and a changelog entry crediting @SebTardif. Production code is unchanged from this PR. Codex autoreview returned scoped-clean for the original patch and follow-up (the skill's default P0 scope). Existing GitHub CI is green. The PR is behind main; the original code delta merges cleanly. The landing workflow should carry the support commit and retain main's existing maintenance notes when integrating its changelog entry. |
Document repeated-cursor failures and make their regression checks tolerate slow database setup while still asserting exactly two requests. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Preserve the existing Unreleased maintenance notes alongside the pagination fix. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: fix(api): stop Slack pagination on a repeated cursor This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
steipete
left a comment
There was a problem hiding this comment.
Reviewed the final patch with the maintainer regression-test repair and additive changelog reconciliation. Local Slack API tests, vet, and CLI smoke passed; all CI checks passed on fec9d2a. Codex autoreview found no actionable findings in its default P0 scope. The earlier synthetic built-CLI proof covers all four repeated-cursor paths and normal pagination. Ready to land; thanks @SebTardif.
|
Landed as f04f3c5, including the test/docs follow-up and existing maintenance notes. Thanks @SebTardif! Final head fec9d2a passed |
Preserve all Unreleased fixes and maintenance notes after landing openclaw#159. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Preserve all Unreleased fixes and maintenance notes after landing openclaw#159 and openclaw#163. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
What Problem This Solves
Fixes an issue where users running
slacrawl sync(or any path that pages Slack conversations, channel history, thread replies, or DMs) would hang until the process was killed when Slack kept returning the samenext_cursor. Channel listing, history backfill, thread replies, and DM listing all followed that token with no stop condition.Why This Change Was Made
A stuck Slack cursor is a hang, not a slow page. MCP
tools/listin this repo already rejects a repeated cursor. The Slack HTTP loops did not. This copies that fail-closed check ontoconversations.list,conversations.history,conversations.replies, and DM listing. Same class as openclaw/notcrawl#102 and openclaw/discrawl#181.The unguarded loops date to bootstrap PR #1 (
df45322) on 2026-03-07. DM listing added the same pattern in PR #12 (ffd4ad6) on 2026-04-23.User Impact
A wedged Slack pager now stops with a clear
repeated cursorerror instead of spinning until someone kills the sync. Successful pages (empty cursor, or a new cursor) are unchanged.Evidence
terminal output from the patched Slack client. A
conversations.listpager that always returnsnext_cursor=stucknow fails closed after two pages.Before this patch the same pager never returned. A 300ms deadline expired with:
After this patch (
6fc35a7346538fec822532a0e381e43ec3d933d8) the same pager returns immediately:Channel history, thread replies, and DM listing use the same stop. Those four paths return in about 0.00s to 0.01s instead of waiting out the deadline:
Real behavior proof
Behavior or issue addressed: Slack conversation, history, thread, and DM pagers followed a repeated
next_cursorforever, soslacrawl syncnever returned.Real environment tested: macOS Darwin arm64, Go 1.26.6, full clone of openclaw/slacrawl at
/tmp/pr-slacrawlonfix/slack-repeated-cursor(6fc35a7346538fec822532a0e381e43ec3d933d8).Exact steps or command run after this patch:
Evidence after fix: terminal output from the patched Slack client. The stuck
conversations.listpager now printsconversations.list repeated cursor "stuck"and returns in 0.00s instead of hanging until the 300ms deadline:Observed result after fix: After two pages with the same
next_cursor=stuck,fetchChannelsreturnsconversations.list repeated cursor "stuck"before the 300ms deadline. History, replies, and DM listing do the same for their Slack methods.What was not tested: A live Slack workspace that actually repeats
next_cursor. slack-goGetUsersContextpagination inside the library was left unchanged.