You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The #674 gate (PR #720) discovers 60 broad catch clauses in production source sets with no preceding cancellation clause, recorded in scripts/cancellation-catch-backlog.tsv. This issue is their tracking home.
Why this issue exists
#720's backlog rows originally cited #667, which was closed COMPLETED on 2026-09-02 — and was scoped to its own six app/src/main sites, never to this list. #674 itself closes when #720 merges. Without this issue the entire backlog would cite two closed issues on the day it landed, invisible to any open-state triage filter, in a file whose own header says its purpose is not to become "the place things go to be forgotten."
(My error: I told #720's author that #667 was the natural consumer for these findings. It was already closed when I said it.)
The work
Each row needs triage, and the triage is not "add a cancellation clause to all 60."
Reachability first, severity second. A try whose guarded call never suspends cannot take delivery of a CancellationException at all — such a site is latent, not live, and a mechanical fix adds noise without removing risk. This distinction has already produced one false finding in this repo: #667's own sweep tabulated what each catch body does without a column for whether the exception can be delivered, and two separate readers independently read that as a list of live defects. It was not.
So for each row establish, and record:
Can the guarded call actually deliver cancellation? Does anything inside the try suspend? Is the enclosing scope ever cancelled?
If yes — live. Add the cancellation clause before the broad one and fix the ordering.
If no — latent. Say why in the row's reason, and it stays as documented debt rather than becoming a churn PR.
Useful discriminators in this codebase: does the scope ever get cancelled; does the guarded call actually suspend; is the state written observable after teardown. All three produced "latent, not live" verdicts on #667.
Notes
IllegalStateException is the dangerous member of the broad set — CancellationException extends it on the JVM, so the clause reads as narrow and deliberate while catching exactly what the author believed they had excluded.
Source order is the only enforcement. Kotlin diagnoses neither an unreachable nor a mis-ordered catch clause. A suspend function compiles to multiple exception-table ranges, and a guard correct in one is not automatically correct in another — Stop renewal auth providers swallowing cancellation (#670) #673 adjudicated a hard case by reading the compiled exception table, which is the standard if a row is genuinely ambiguous.
The #674 gate (PR #720) discovers 60 broad catch clauses in production source sets with no preceding cancellation clause, recorded in
scripts/cancellation-catch-backlog.tsv. This issue is their tracking home.Why this issue exists
#720's backlog rows originally cited #667, which was closed COMPLETED on 2026-09-02 — and was scoped to its own six
app/src/mainsites, never to this list. #674 itself closes when #720 merges. Without this issue the entire backlog would cite two closed issues on the day it landed, invisible to any open-state triage filter, in a file whose own header says its purpose is not to become "the place things go to be forgotten."(My error: I told #720's author that #667 was the natural consumer for these findings. It was already closed when I said it.)
The work
Each row needs triage, and the triage is not "add a cancellation clause to all 60."
Reachability first, severity second. A
trywhose guarded call never suspends cannot take delivery of aCancellationExceptionat all — such a site is latent, not live, and a mechanical fix adds noise without removing risk. This distinction has already produced one false finding in this repo: #667's own sweep tabulated what each catch body does without a column for whether the exception can be delivered, and two separate readers independently read that as a list of live defects. It was not.So for each row establish, and record:
trysuspend? Is the enclosing scope ever cancelled?Useful discriminators in this codebase: does the scope ever get cancelled; does the guarded call actually suspend; is the state written observable after teardown. All three produced "latent, not live" verdicts on #667.
Notes
IllegalStateExceptionis the dangerous member of the broad set —CancellationExceptionextends it on the JVM, so the clause reads as narrow and deliberate while catching exactly what the author believed they had excluded.suspendfunction compiles to multiple exception-table ranges, and a guard correct in one is not automatically correct in another — Stop renewal auth providers swallowing cancellation (#670) #673 adjudicated a hard case by reading the compiled exception table, which is the standard if a row is genuinely ambiguous.Related: #619, #661, #674, #720, #721.