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)
|
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.