Read a channel Discord denies as unavailable, not a failed backfill - #83
Open
lucasrcezimbra wants to merge 4 commits into
Open
Read a channel Discord denies as unavailable, not a failed backfill#83lucasrcezimbra wants to merge 4 commits into
lucasrcezimbra wants to merge 4 commits into
Conversation
A history backfill that Discord answers with Missing Access (50001) or Missing Permissions (50013) is a permission somebody set, not a backfill that broke. It now records its own append-only outcome — backfill_run_unavailabilities — instead of a failure row, and does not rethrow, so the scheduler stops burning five retries on a permission that cannot change inside its backoff. ingestion_status counts those channels apart from the failed ones and names them under unavailableChannelNames, with copy that says no action is needed unless the owner wants them ingested — in which case a server admin, who may not be the owner, grants View Channel and Read Message History. Denied channels stay in the reconnect sweep, so a permission granted later heals the reading on its own. Closes seasonedcc#82 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The failed status told the owner a restart prints what stopped every backfill that keeps giving up, but a backfill stopped at the page limit returns without throwing, so the daemon never prints anything for it. The advice now scopes the print to backfills that keep stopping on an error, which is the only cause the scheduler logs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The one-final-sweep rule counted any post-archiving run as the final sweep, outcome ignored. An archived thread whose final attempt was denied, stopped on an error, or hit the page limit was never swept again, so its status read failed forever while the guidance promised a restart would resume it — a restart that never re-attempted the thread. Now only a completion spends the final sweep: an unfinished attempt is retried on the next reconnect exactly like a live channel, so a denial heals to unavailable and a page-limit stop keeps advancing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The unavailable copy and the README said nothing from a denied channel is in the store, and no catch-up, mention or digest can include it. A channel ingested before the denial keeps its history, and every reader still serves it — the denial stops new history, not the stored kind. The copy now says exactly that. Also drops the demonstration's failed-count check that the unavailable roll-up already makes unreachable, since failed outranks unavailable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lucasrcezimbra
marked this pull request as ready for review
August 17, 2026 17:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Discord answers
Missing Accesswhen the bot sits in a channel it has no permission to read the history of. Until now that landed inbackfill_run_failureslike any other broken backfill, soingestion_statusreported the channel as failed, implied history was missing, and told the owner to grant Read Message History — an action the owner often cannot take, because they may not be a server admin. An assistant reading that status had no way to tell a permission somebody set on purpose from an outage worth escalating.What an unavailable channel is. A backfill whose Discord call comes back
Missing Access(50001) orMissing Permissions(50013) now records a singlebackfill_run_unavailabilitiesrow — its own append-only outcome, no failure row.ingestion_statuscounts those channels underchannels.unavailable, names them underunavailableChannelNames, and keepsfailedChannelNamesfor backfills that genuinely stopped short. The copy says no action is needed unless the owner wants those channels ingested, in which case a server admin grants View Channel and Read Message History.How status reads.
unavailableranks belowreactionsUnreadand abovecompleted: every actionable state still outranks it, so a real problem is never hidden behind a permission — and a store that cannot see a channel never claims to be fully caught up either.Retry semantics. The error is not rethrown, so the scheduler stops burning five attempts on a permission that cannot change inside its backoff. The channel is deliberately not excluded from
listBackfillableChannels, so the next gateway connect re-attempts it exactly once — an admin granting access later heals the reading with no bookkeeping to undo.Archived threads heal too. The one-final-sweep rule used to spend an archived thread's single post-archiving sweep on any attempt, outcome ignored — a thread whose final sweep was denied (or stopped on an error, or hit the page limit) was never swept again and read
failedforever, while the guidance promised a restart would resume it. Only a completed run spends the final sweep now: an unfinished attempt is re-tried on the next reconnect exactly like a live channel, so a denied archived thread readsunavailable, and a long one keeps advancing past a page-limit stop instead of stranding its history.Rulings worth arguing.
backfill_run_failuresuntouched. Splitting them would ship two copies of one next action.kindcolumn tobackfill_run_failureswould reshape an existing event table, which the append-only doctrine forbids — and it would keep calling a permission a failure. The sibling precedent isbackfill_run_unread_reactions.channels_listuntouched. The channel is visible in Discord, just unreadable, so it stays in the list —ingestion_statusis the health surface the other tools already point to, and duplicating the signal would give the concept a second home to drift in.The
failedguidance was also re-ruled to fit what remains in it: it no longer suggests granting a permission, and it promises the daemon's diagnostic print only for backfills that keep stopping on an error — a backfill stopped at the page limit returns without throwing, so nothing is ever printed for it.The dev seed now ships a
#leadershipchannel Discord denies, so the demo store shows the distinction before anyone invites a bot; the README anddocs/architecture.mdteach it.Closes #82
🤖 Generated with Claude Code