zylon-ai/private-gpt · error · TimeoutError

Task did not complete within {self.poll_timeout} seconds

Error message

Task did not complete within {self.poll_timeout} seconds

What it means

Raised by AsyncDoclingClient._wait_for_completion when the polling loop exceeds poll_timeout seconds without the task reaching success/failure/skipped. Important subtlety from the loop condition `while not self.poll_timeout or time.time() - start_time < self.poll_timeout`: if poll_timeout is None or 0, the client polls forever and this error can never fire; it only fires when a positive docling.pool_timeout (or poll_timeout constructor arg) was configured.

Source

Thrown at private_gpt/components/readers/docling/api_clients.py:502

            response.raise_for_status()
            result = await response.json()
            return DoclingApiOutputModel(**result)

    async def _wait_for_completion(self, task_id: str) -> DoclingApiOutputModel:
        start_time = time.time()
        while not self.poll_timeout or time.time() - start_time < self.poll_timeout:
            status = await self._poll_task_status(task_id)
            if status.task_status == "success":
                task_result: DoclingApiOutputModel = await self._get_task_result(
                    task_id
                )
                return task_result
            if status.task_status in ["failure", "skipped"]:
                raise ValueError(f"Task failed with status: {status.task_status}")

            await asyncio.sleep(self.poll_interval)

        raise TimeoutError(f"Task did not complete within {self.poll_timeout} seconds")

    @retry(
        is_async=True,
        tries=_MAX_RETRIES,
        jitter=_JITTER,
        logger=logger,
        exceptions=ResourceNotFoundError,
    )
    async def convert_from_bytes(
        self, file_name: str, file_bytes: bytes, **kwargs: Any
    ) -> DoclingApiOutputModel:
        task_id = await self._submit_task(file_name, file_bytes, **kwargs)
        return await self._wait_for_completion(task_id)


class DoclingClientFactory:
    @staticmethod
    def create(config: DoclingConfig, async_client: bool = False) -> BaseDoclingClient:

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Increase docling.pool_timeout in settings.yaml to a realistic value for your documents (large PDFs with OCR commonly need 600-1800s).
  2. Check Docling server load/queue depth (GET /status/poll/{task_id} shows task_position) — scale the server or reduce concurrent ingests.
  3. Reduce work per task: limit pages via the pages config, disable OCR for digital-native PDFs, or set do_ocr: false.
  4. Verify the server is actually progressing (watch task_position across polls) rather than deadlocked.
  5. Catch TimeoutError at the call site and re-submit or surface a retry-able failure to the user instead of crashing the ingestion batch.

Example fix

# settings.yaml — before
# docling:
#   pool_timeout: 60

# after
# docling:
#   pool_timeout: 1800

# call-site guard
try:
    result = await client.convert_from_bytes(name, data)
except TimeoutError:
    logger.warning("Docling task for %s timed out; requeueing", name)
    raise
Defensive patterns

Strategy: retry

Validate before calling

# sanity-check timeout vs workload before submitting
pages = file_info.config.get("pages")
estimated = estimate_seconds(pages or default_page_count)
if docling_cfg.pool_timeout and docling_cfg.pool_timeout < estimated:
    logger.warning("pool_timeout=%s may be too small for ~%ss of work", docling_cfg.pool_timeout, estimated)

Try / catch

import asyncio

for attempt in range(2):
    try:
        return await client.convert_from_bytes(file_name, file_bytes)
    except TimeoutError:
        if attempt == 1:
            raise
        await asyncio.sleep(10)  # server may still be draining; one re-submit

Prevention

When it happens

Trigger: Calling convert_from_bytes on AsyncDoclingClient with docling.pool_timeout set (e.g., 600s) while the server keeps returning a pending status — long queue position, heavy load, large multi-hundred-page documents, or a server that is up but stalled. The error message interpolates the configured timeout value.

Common situations: Under-provisioned Docling server (CPU-only) processing large PDFs with OCR enabled; many concurrent ingests saturating the server queue; poll_interval set high so checks are sparse near the deadline; timeout configured for sync expectations (30-60s) while async tasks legitimately take minutes.

Understand the failure class

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/d6d6cfd95ee5e15b. Report an issue: GitHub.