Textualize/textual · warning · WorkerCancelled

Worker was cancelled, and did not complete.

Error message

Worker was cancelled, and did not complete.

What it means

WorkerCancelled raised by Worker.wait(): the worker finished in CANCELLED state (its task was cancelled, e.g. via worker.cancel() or app shutdown), so there is no result to return. wait() re-raises cancellation to the awaiting caller instead of returning None.

Source

Thrown at src/textual/worker.py:454

                    "Can't call worker.wait from within the worker function!"
                )
        except LookupError:
            # Not in a worker
            pass

        if self.state == WorkerState.PENDING:
            raise WorkerError("Worker must be started before calling this method.")
        if self._task is not None:
            try:
                await self._task
            except asyncio.CancelledError as error:
                self.state = WorkerState.CANCELLED
                self._error = error
        if self.state == WorkerState.ERROR:
            assert self._error is not None
            raise WorkerFailed(self._error)
        elif self.state == WorkerState.CANCELLED:
            raise WorkerCancelled("Worker was cancelled, and did not complete.")
        return cast("ResultType", self._result)

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Catch WorkerCancelled where cancellation is expected and treat it as a no-op: `except WorkerCancelled: pass`.
  2. Avoid awaiting workers that exclusive replacement may cancel, or re-check state afterwards.
  3. For cleanup-on-cancel, use try/finally inside the worker body.

Example fix

# before
result = await worker.wait()
# after
from textual.worker import WorkerCancelled
try:
    result = await worker.wait()
except WorkerCancelled:
    result = None
Defensive patterns

Strategy: try-catch

Validate before calling

from textual.worker import WorkerState
if worker.state != WorkerState.CANCELLED:
    result = await worker.wait()

Try / catch

from textual.worker import WorkerCancelled
try:
    result = await worker.wait()
except WorkerCancelled:
    result = None

Prevention

When it happens

Trigger: `await worker.wait()` after `worker.cancel()` was called; cancellation triggered by exclusive workers (a new worker with exclusive=True cancels the previous one); or the app/screen shutting down cancels pending workers.

Common situations: Overlapping triggers of the same @work method with exclusive=True; awaiting a worker during app exit; user retriggers a search/load before the previous finished.

Related errors


AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27). Data as JSON: /api/errors/39e1ecd69389c850. Report an issue: GitHub.