docling-project/docling · error · TaskNotFoundError
Task {task_id} was not found.
Error message
Task {task_id} was not found. What it means
TaskNotFoundError raised by the WebSocket status watcher when the service sends an error frame with exactly 'Task not found.' over WS /v1/status/ws/{task_id}. It means the task id is unknown to the service — expired from the result backend, never existed, or was purged after completion.
Source
Thrown at docling/service_client/watchers.py:57
) -> float:
elapsed = time.monotonic() - poll_started
remaining = deadline - time.monotonic()
if remaining <= 0:
return 0.0
return max(0.0, min(poll_interval, remaining) - elapsed)
def _process_ws_envelope(
envelope: WebsocketMessage,
task_id: str,
) -> TaskStatusResponse | None:
"""Return the TaskStatusResponse from an envelope, or None for CONNECTION frames.
Raises TaskNotFoundError or ServiceUnavailableError on error frames.
"""
if envelope.error:
if envelope.error == "Task not found.":
raise TaskNotFoundError(f"Task {task_id} was not found.")
raise ServiceUnavailableError(
"WebSocket status stream failed.",
detail=envelope.error,
)
return envelope.task
class StatusWatcher(Protocol):
"""Protocol for job status watchers."""
def iter_updates(
self, task_id: str, timeout: float | None
) -> Iterator[TaskStatusResponse]: ...
def wait_for_terminal(
self, task_id: str, timeout: float | None
) -> TaskStatusResponse: ...
View on GitHub (pinned to 61d76f1ff3)
Solutions
- Handle TaskNotFoundError as terminal — resubmit the conversion instead of re-polling
- If tasks must survive restarts, configure a persistent result backend (redis/database) in docling-serve
- Store task ids only as long as the service's task TTL allows
Example fix
try:
status = watcher.wait_for_terminal(task_id)
except TaskNotFoundError:
result = client.submit(Path('doc.pdf')) # resubmit Defensive patterns
Strategy: try-catch
Type guard
def is_task_not_found(exc: BaseException) -> bool:
return isinstance(exc, TaskNotFoundError) Try / catch
from docling.service_client.exceptions import TaskNotFoundError
try:
status = watcher.wait_for_terminal(task_id)
except TaskNotFoundError:
task_id = resubmit_and_get_new_id() Prevention
- Resubmit on TaskNotFoundError instead of re-polling — the id is gone
- Use a persistent task/result backend in docling-serve if ids must survive restarts
- Consume task results before the service's task TTL expires
When it happens
Trigger: Opening the status WebSocket for a task id that finished and was evicted, a fabricated/typo'd id, or a task record lost after a service restart while the client was waiting.
Common situations: Waiting on tasks across a service redeploy (in-memory task store wiped); result TTL expiry before the client re-attached; copy-paste errors in persisted task ids.
Related errors
- Timed out waiting for task {task_id} after {wait_timeout:.2f
- WebSocket status stream is unavailable.
- Task {task_id} was not found.
- Timed out waiting for task {task_id} to emit status updates.
- Timed out waiting for task {task_id} after {timeout:.2f}s.
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/376e353132dd64ba.
Report an issue: GitHub.