PaddlePaddle/PaddleOCR · error · PollTimeoutError

Timed out after {elapsed:.1f}s waiting for job {job_id}

Error message

Timed out after {elapsed:.1f}s waiting for job {job_id}

What it means

PollTimeoutError raised by the poller's top-of-loop deadline check: the asynchronous OCR/PP-StructureV3 job did not reach 'done' or 'failed' within max_wait_time seconds. The poller uses exponential backoff (initial_interval * multiplier capped at max_interval) and gives up once time.monotonic() passes the deadline computed at poll start.

Source

Thrown at paddleocr/_api_client/_poller.py:67

        multiplier: float = DEFAULT_MULTIPLIER,
        max_interval: float = DEFAULT_MAX_INTERVAL,
        max_wait_time: float = DEFAULT_MAX_WAIT_TIME,
    ):
        self._http = http_client
        self._initial_interval = initial_interval
        self._multiplier = multiplier
        self._max_interval = max_interval
        self._max_wait_time = max_wait_time

    def poll_until_done(self, job_id: str) -> Any:
        interval = self._initial_interval
        start = time.monotonic()
        deadline = start + self._max_wait_time

        while True:
            now = time.monotonic()
            if now >= deadline:
                raise PollTimeoutError(job_id, now - start)

            data = self._http.get_job_status(job_id)
            state = validate_state(data)

            if state == "done":
                json_url = validate_result_json_url(data)
                jsonl_data = self._http.fetch_jsonl(json_url)
                return jsonl_data, data

            if state == "failed":
                error_msg = data.get("errorMsg", "Unknown error")
                raise JobFailedError(job_id, error_msg)

            remaining = deadline - time.monotonic()
            if remaining <= 0:
                raise PollTimeoutError(job_id, time.monotonic() - start)

            time.sleep(min(interval, remaining))

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Retry the poll — the job usually still completes server-side; re-poll with poller.get_status(job_id) or a fresh poll_until_done call with a larger budget
  2. Increase max_wait_time (and optionally max_interval) when constructing the poller for large documents or batches
  3. Check job status manually once after the timeout to see whether it eventually finishes, then fetch the result URL directly
  4. If jobs never finish, investigate server capacity / job queue state rather than the client timeout

Example fix

# before
poller = JobPoller(http, max_wait_time=300)  # times out on big PDFs
jsonl, raw = poller.poll_until_done(job_id)

# after
poller = JobPoller(http, max_wait_time=1800, max_interval=30)
jsonl, raw = poller.poll_until_done(job_id)
Defensive patterns

Strategy: retry

Validate before calling

# no pre-call validation possible; estimate budget from input size
pages = count_pages(pdf_path)
max_wait = max(300, pages * 30)  # rough seconds-per-page budget

Try / catch

from paddleocr._api_client.errors import PollTimeoutError
try:
    jsonl, raw = poller.poll_until_done(job_id)
except PollTimeoutError:
    status = poller.get_status(job_id)  # job may still finish
    raise

Prevention

When it happens

Trigger: Calling an async submit-and-poll API (e.g. submit a large PDF for OCR) with a max_wait_time shorter than the server's actual processing time; the job stays in a pending/running state past the configured budget. The check fires on the first loop iteration whose time.monotonic() >= deadline.

Common situations: Large multi-page documents on a slow or shared PaddleOCR backend; server queue congestion; max_wait_time left at a default too small for batch workloads; network latency inflating each get_job_status round trip so fewer polls fit in the budget.

Understand the failure class

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/67de69f9f886a636. Report an issue: GitHub.