Textualize/textual · error · WorkerError
Unsupported attempt to run a thread worker
Error message
Unsupported attempt to run a thread worker
What it means
WorkerError raised in Worker._run_threaded: the work object is neither a coroutine, an awaitable, nor callable, so the thread-pool runner cannot execute it. This indicates a misconfigured Worker rather than a runtime failure.
Source
Thrown at src/textual/worker.py:322
return run_awaitable(work())
def run_callable(work: Callable[[], ResultType]) -> ResultType:
"""Set the active worker, and call the callable."""
active_worker.set(self)
return work()
if (
inspect.iscoroutinefunction(self._work)
or hasattr(self._work, "func")
and inspect.iscoroutinefunction(self._work.func)
):
runner = run_coroutine
elif inspect.isawaitable(self._work):
runner = run_awaitable
elif callable(self._work):
runner = run_callable
else:
raise WorkerError("Unsupported attempt to run a thread worker")
loop = asyncio.get_running_loop()
assert loop is not None
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):View on GitHub (pinned to 06dbeef4bb)
Solutions
- Pass a plain function to thread workers: `run_worker(my_function, thread=True)`.
- Ensure the object is callable (`callable(obj)`) before scheduling.
- Don't pass coroutines to thread workers — those take the async path.
Example fix
# before self.run_worker(result, thread=True) # after self.run_worker(load_data, thread=True)
Defensive patterns
Strategy: validation
Validate before calling
import inspect
if not (inspect.isawaitable(work) or callable(work)):
raise ValueError('work must be callable or awaitable') Type guard
def is_runnable(w: object) -> bool:
return callable(w) or inspect.isawaitable(w) Try / catch
from textual.worker import WorkerError
try:
self.run_worker(work, thread=True)
except WorkerError as e:
log(e) Prevention
- Always pass a function object to thread workers
- Validate dynamic work items before scheduling
When it happens
Trigger: Constructing Worker (or calling run_worker with thread=True) with a non-callable — e.g. an already-consumed coroutine's result, an int/str, or an object whose __call__ was removed. Rare; usually surfaces in tests or dynamic dispatch.
Common situations: Passing a variable that was accidentally awaited/consumed earlier; passing a class instead of an instance with __call__.
Related errors
- Request to run a non-async function as an async worker
- Can not create a worker from a non-async function unless `th
- {self.name} must be a str
- Invalid color value {color}
- unable to display {obj.__class__.__name__!r} type; must be a
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/3b7b94f6487d31a4.
Report an issue: GitHub.