affaan-m/ECC · warning
announcement delivered; pending receipt cleanup requires…
Error message
announcement delivered; pending receipt cleanup requires attention
What it means
In release-announce.mjs, after the Discord webhook delivers the announcement and the success receipt comment is added, the script deletes the temporary claim receipt. If that deletion fails, it logs this warning instead of failing — the announcement was delivered, but a pending receipt comment remains on the discussion and needs manual cleanup.
Solutions
- Manually delete the leftover claim receipt comment (identified by the receipt marker) from the GitHub discussion
- Re-run the release-announce script in a dry/check mode if available to verify no other receipts are pending
- Check the GitHub token's permissions (needs comment deletion rights) and any API rate-limit events in the run window
- If transient, no action beyond cleanup is needed — the announcement itself was delivered
Example fix
# before (manual cleanup)
# find comment containing the receipt marker on the discussion and delete it
# after: hardened cleanup with retry in the script
await deleteReceiptComment(claimId).catch(async e => {
await new Promise(r => setTimeout(r, 1000));
return deleteReceiptComment(claimId);
}).catch(() => console.warn('announcement delivered; pending receipt cleanup requires attention')); Defensive patterns
Strategy: retry
Validate before calling
// before delivery, confirm token can manage comments
const probe = await octokit.rest.issues.getComment({ owner, repo, comment_id: claimId });
if (!probe.data) console.warn('claim receipt missing before delivery'); Try / catch
await deleteReceiptComment(claimId).catch(err => retryDelete(claimId, 3))
.catch(() => console.warn('announcement delivered; pending receipt cleanup requires attention')); Prevention
- Use a GitHub token with repo/issues comment write and delete permissions
- Add retry-with-backoff around receipt comment deletion
- Monitor for the receipt marker after runs and clean up leftovers promptly
- Avoid concurrent release-announce runs against the same discussion
When it happens
Trigger: deleteReceiptComment(claimId) rejects (e.g. GitHub API error, permission issue, or the comment was already removed) inside the .catch() after successful webhook delivery; deliver() completes but leaves the claim receipt behind.
Common situations: GitHub API transient failure or rate limit right after Discord delivery; token lacking permission to delete issue comments; concurrent runs where another process already consumed/deleted the claim receipt.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Discord webhook request failed
- Announcements discussion category is required
- Discord announcement credentials are missing or invalid
- discussion lookup failed
- discussion number is invalid
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/2e10f3d2ba23847e.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/discord/release-announce.mjs:177
throw new Error('announcement has a pending receipt; inspect Discord before clearing it');
}
const claimId = await addReceiptComment(discussion.id, `${marker}\n\nDiscord delivery: pending.`);
const payload = buildDiscordPayload({ title: discussion.title, body: discussion.body, url: discussion.url, key });
delete payload.nonce;
delete payload.enforce_nonce;
const response = await request(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!response.ok) {
await deleteReceiptComment(claimId);
throw new Error(`Discord webhook request failed (${response.status})`);
}
const message = await response.json();
await addReceiptComment(discussion.id, `${marker}\n\nDiscord delivery: complete (message ${message.id}).`);
await deleteReceiptComment(claimId).catch(() => {
console.warn('announcement delivered; pending receipt cleanup requires attention');
});
console.log('announcement delivered by channel webhook');
return;
}
if (!env.DISCORD_BOT_TOKEN || !/^\d{10,25}$/.test(env.DISCORD_ANNOUNCE_CHANNEL_ID || '')) {
throw new Error('Discord announcement credentials are missing or invalid');
}
const recent = await discord('GET', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/messages?limit=100`);
const receipt = findDiscordReceipt(recent, key);
if (receipt) {
await discord('PUT', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/pins/${receipt.id}`);
console.log('announcement already delivered; pin verified');
return;
}
const message = await discord('POST', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/messages`, buildDiscordPayload({
title: discussion.title,
body: discussion.body,
url: discussion.url,View on GitHub (pinned to 8321021c54)