Textualize/textual · error · WorkerError

Unsupported attempt to run an async worker

Error message

Unsupported attempt to run an async worker

What it means

WorkerError from Worker._run_async: the work item matches none of the supported async kinds (partial of coroutine function, awaitable, callable). It is effectively unreachable for well-typed inputs and signals an internal/unsupported work object in async mode.

Source

Thrown at src/textual/worker.py:344

        return await loop.run_in_executor(None, runner, self._work)

    async def _run_async(self) -> ResultType:
        """Run an async worker.

        Returns:
            Return value of the work.
        """
        if (
            inspect.iscoroutinefunction(self._work)
            or hasattr(self._work, "func")
            and inspect.iscoroutinefunction(self._work.func)
        ):
            return await self._work()
        elif inspect.isawaitable(self._work):
            return await self._work
        elif callable(self._work):
            raise WorkerError("Request to run a non-async function as an async worker")
        raise WorkerError("Unsupported attempt to run an async worker")

    async def run(self) -> ResultType:
        """Run the work.

        Implement this method in a subclass, or pass a callable to the constructor.

        Returns:
            Return value of the work.
        """
        return await (
            self._run_threaded() if self._thread_worker else self._run_async()
        )

    async def _run(self, app: App) -> None:
        """Run the worker.

        Args:
            app: App instance.

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Ensure the work passed to run_worker is an async function, a partial thereof, or an awaitable.
  2. Use a plain function with thread=True for sync work.
  3. Type-check before scheduling: `if not (inspect.isawaitable(w) or callable(w)): raise ValueError`.

Example fix

# before
self.run_worker(some_object)
# after
self.run_worker(asyncio.to_thread(sync_fn))  # awaitable, runs blocking fn
Defensive patterns

Strategy: validation

Validate before calling

import inspect
if not (inspect.isawaitable(w) or inspect.iscoroutinefunction(w) or callable(w)):
    raise ValueError('unsupported work item')

Type guard

def is_async_work(w) -> bool:
    import inspect
    return inspect.isawaitable(w) or callable(w)

Try / catch

from textual.worker import WorkerError
try:
    await worker.run()
except WorkerError as e:
    raise RuntimeError(f'bad worker config: {e}') from e

Prevention

When it happens

Trigger: Passing an object that is not awaitable and not callable to an async worker — e.g. a data value or an object whose __call__ raises on inspection edge cases; almost always from direct Worker construction with invalid work.

Common situations: Dynamic/generic code that forwards arbitrary objects into run_worker; subclassing Worker and setting _work incorrectly.

Related errors


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