docling-project/docling · error · TaskTimeoutError

Timed out waiting for task {task_id} after {timeout:.2f}s.

Error message

Timed out waiting for task {task_id} after {timeout:.2f}s.

What it means

_wait_for_terminal_status polls the task with long-poll waits until a monotonic deadline. When the deadline (submission time + timeout) passes before the task reaches a terminal status, TaskTimeoutError is raised, reporting the task id and the configured timeout. The task may still be running server-side; only the client gave up waiting.

Source

Thrown at docling/service_client/_async_client.py:893

        if response.status_code == 404:
            raise TaskNotFoundError(f"Task {task_id} was not found.")
        if response.status_code != 200:
            self._raise_for_generic_http_error(
                response, f"Polling task {task_id} failed."
            )
        return TaskStatusResponse.model_validate_json(response.text)

    async def _wait_for_terminal_status(
        self,
        task_id: str,
        timeout: float,
        async_client: httpx.AsyncClient,
    ) -> TaskStatusResponse:
        deadline = time.monotonic() + timeout
        while True:
            remaining = deadline - time.monotonic()
            if remaining <= 0:
                raise TaskTimeoutError(
                    f"Timed out waiting for task {task_id} after {timeout:.2f}s."
                )
            wait = min(self._poll_server_wait, remaining)
            logger.info("Polling status for task_id=%s wait=%.2fs", task_id, wait)
            poll_started = time.monotonic()
            update = await self._poll_task_status_using_client(
                task_id=task_id,
                wait=wait,
                async_client=async_client,
            )
            logger.info(
                "Received status for task_id=%s status=%s position=%s",
                task_id,
                update.task_status,
                update.task_position,
            )
            if is_terminal_task_status(update):
                return update

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Increase the timeout passed to the wait/conversion call.
  2. Reduce service load or scale docling-serve (more workers/GPUs) so tasks finish faster.
  3. Split very large documents into smaller conversion requests.
  4. Catch TaskTimeoutError and poll again later — the task may still complete and can be retrieved by id.

Example fix

# before
result = await client.convert_and_get(f, timeout=60.0)  # TaskTimeoutError on big file

# after
from docling.service_client.exceptions import TaskTimeoutError
try:
    result = await client.convert_and_get(f, timeout=900.0)
except TaskTimeoutError:
    await asyncio.sleep(300)
    result = await client.get_task_result(task_id)  # pick up later
Defensive patterns

Strategy: retry

Try / catch

from docling.service_client.exceptions import TaskTimeoutError

try:
    result = await client.convert_and_get(f, timeout=900.0)
except TaskTimeoutError:
    await asyncio.sleep(300)
    result = await client.get_task_result(task_id)  # task may be done by now

Prevention

When it happens

Trigger: Large documents or busy service making conversion exceed the configured timeout; timeout set too small for queued tasks (position in queue high); GPU-less service processing many pages slowly; deadlock/overload on the service so the task never completes.

Common situations: Default timeouts with 500+ page PDFs; batch submissions saturating the service; cold model load on first request taking minutes; network latency inflating each long-poll round trip.

Understand the failure class

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/694d21fd6fb2645f. Report an issue: GitHub.