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
- 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
- Increase max_wait_time (and optionally max_interval) when constructing the poller for large documents or batches
- Check job status manually once after the timeout to see whether it eventually finishes, then fetch the result URL directly
- 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
- Size max_wait_time from document size, not a constant
- For large batches, use get_batch_status instead of per-job polling budgets
- Persist the job_id so a timed-out job can be re-polled instead of resubmitted
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Document parsing result item is missing result.layoutParsing
- Job ${job.jobId} is a ${job.task} job, not a ${expectedTask}
- Timed out after ${timeoutMs}ms waiting for job ${jobId}
- Timed out after {elapsed:.1f}s waiting for job {job_id}
- Job {job_id} failed: {error_msg}
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/67de69f9f886a636.
Report an issue: GitHub.