affaan-m/ECC · error · Error
discussion receipt lookup exceeded page budget
Error message
discussion receipt lookup exceeded page budget
What it means
findReceiptComment caps pagination at 50 pages of 100 comments (5000 comments). If the marker receipt comment has not been found after exhausting that budget, it throws instead of looping forever on a runaway or extremely large discussion.
Solutions
- Increase the page budget (e.g. `for (let page = 0; page < 200; ...)`) if discussions legitimately exceed 5000 comments
- Verify the receipt is actually posted by running addReceiptComment once and checking for duplicate-delivery logic elsewhere
- Confirm pagination advances: log endCursor each iteration to detect a stuck cursor
- Search comments server-side is not supported; consider storing receipts as a single pinned comment checked first
Example fix
// before
for (let page = 0; page < 50; page += 1) {
// after
const MAX_PAGES = Number(env.RECEIPT_MAX_PAGES || 50);
for (let page = 0; page < MAX_PAGES; page += 1) { Defensive patterns
Strategy: try-catch
Validate before calling
// sanity-check comment count is within the budget
const count = await githubGraphql('query($id:ID!){node(id:$id){... on Discussion{comments(first:1){totalCount}}}}', { id: discussionId });
const total = count.node?.comments?.totalCount ?? 0;
if (total > 5000) throw new Error(`Discussion has ${total} comments, exceeds 50x100 page budget`); Try / catch
try {
const receipt = await findReceiptComment(discussionId, marker);
} catch (err) {
if (err.message === 'discussion receipt lookup exceeded page budget') {
console.error('Over 5000 comments; raise the page budget or use a dedicated/pinned receipt discussion');
}
throw err;
} Prevention
- Keep announcement discussions lean; use a dedicated discussion per release for receipts
- Make the page budget configurable rather than hardcoded at 50
- Log cursors per page to detect pagination that never advances
- Check receipt existence early via totalCount before paging
When it happens
Trigger: A discussion with more than 5000 comments where the receipt was never posted (or was posted beyond the page budget), or a pagination bug causing endCursor to never advance so hasNextPage stays true.
Common situations: Very high-traffic announcement discussions accumulating thousands of comments; receipt never actually created because a previous run crashed after creating the discussion but before commenting; GraphQL cursor reuse causing repeated pages.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- discussion receipt lookup failed
- Announcements discussion category is required
- discussion is not an Announcement
- GitHub GraphQL request failed
- GitHub GraphQL returned errors
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/053e39b8910f5e8c.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/discord/release-announce.mjs:119
if (discussion.category?.name !== 'Announcements') throw new Error('discussion is not an Announcement');
return { id: discussion.node_id, title: discussion.title, body: discussion.body, url: discussion.html_url };
}
async function findReceiptComment(discussionId, marker) {
let cursor = null;
for (let page = 0; page < 50; page += 1) {
const data = await githubGraphql(
`query($id:ID!,$after:String){node(id:$id){... on Discussion{comments(first:100,after:$after){nodes{id body author{login}} pageInfo{hasNextPage endCursor}}}}}`,
{ id: discussionId, after: cursor },
);
const comments = data.node?.comments;
if (!comments) throw new Error('discussion receipt lookup failed');
const receipt = findDiscussionReceipt(comments.nodes, marker);
if (receipt) return receipt;
if (!comments.pageInfo.hasNextPage) return null;
cursor = comments.pageInfo.endCursor;
}
throw new Error('discussion receipt lookup exceeded page budget');
}
async function addReceiptComment(discussionId, body) {
const data = await githubGraphql(
`mutation($id:ID!,$body:String!){addDiscussionComment(input:{discussionId:$id,body:$body}){comment{id}}}`,
{ id: discussionId, body },
);
return data.addDiscussionComment.comment.id;
}
async function deleteReceiptComment(commentId) {
await githubGraphql(
`mutation($id:ID!){deleteDiscussionComment(input:{id:$id}){clientMutationId}}`,
{ id: commentId },
);
}
async function discord(method, path, body) {View on GitHub (pinned to 8321021c54)