Skip to content

fix: task.cancel()/retry() during kernel close must not raise#1188

Merged
maartenbreddels merged 1 commit into
masterfrom
fix/cancel-after-context-close
Jul 7, 2026
Merged

fix: task.cancel()/retry() during kernel close must not raise#1188
maartenbreddels merged 1 commit into
masterfrom
fix/cancel-after-context-close

Conversation

@maartenbreddels

Copy link
Copy Markdown
Contributor

Found by integration-testing current master in a large solara application: three tracebacked warnings on every kernel close, from RuntimeError: Cannot cancel task, never started.

Sequence

  1. A @task runs; _drop_call_state is registered via context.on_close (the recent memory fix that unpins contexts at close).
  2. Kernel closes → _drop_call_state nulls _cancel/_retry/futures — but the reactive state still reads pending.
  3. Application cleanup running later in the same close does the natural if task.pending: task.cancel()cancel() finds _cancel is None → raises "never started", which is wrong on both counts: it started, and there is simply nothing left to cancel.

Fix

A task that ran always has _cancel set, so state ≠ NOTCALLED with _cancel is None can only mean the call state was dropped at close: cancel()/retry() are now a no-op in that case, and keep raising only for genuinely never-started tasks (misuse detection unchanged).

The regression test reproduces the production ordering: on_close callbacks run LIFO, so a guard registered before the task starts runs after _drop_call_state. Verified: fails on master with exactly the production error, passes with the fix; full task suite (24) green.

🤖 Generated with Claude Code

_drop_call_state (registered via context.on_close to unpin contexts at
kernel close) drops the call bookkeeping including _cancel/_retry, but
the reactive state still reads pending at that point. Application
cleanup code running later in the same close - the common pattern
`if task.pending: task.cancel()` - then hit
"RuntimeError: Cannot cancel task, never started", producing three
tracebacked warnings per kernel close in a production app (heavy log/
Sentry noise; functionally harmless).

A task that ran always has _cancel set, so "state is not NOTCALLED but
_cancel is None" can only mean the call state was dropped: make cancel()
and retry() a no-op there and keep raising only for genuinely
never-started tasks. Regression test reproduces the production ordering
(on_close callbacks run LIFO, so a guard registered before the task
starts runs after the drop).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@maartenbreddels maartenbreddels temporarily deployed to fix/cancel-after-context-close - solara-stable PR #1188 July 7, 2026 10:18 — with Render Destroyed
@maartenbreddels maartenbreddels merged commit 2cc01de into master Jul 7, 2026
30 of 31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant