opendatalab/MinerU · error · TimeoutError
PDF image rendering timeout after {timeout}s for pages {star
Error message
PDF image rendering timeout after {timeout}s for pages {start_page_id + 1}-{end_page_id + 1} What it means
TimeoutError raised by MineRU's parallel PDF page renderer when the executor futures that render page ranges to images do not all complete within the configured timeout (wait(..., timeout=timeout, return_when=ALL_COMPLETED) returns not_done futures). Rendering is split into page-range chunks submitted to a process/thread pool; the message reports the overall timeout and the 1-based page span requested. The executor is flagged for recycling (recycle_executor = True) because a worker is presumed stuck, and remaining futures are abandoned.
Source
Thrown at mineru/utils/pdf_image_tools.py:316
futures = []
future_to_range = {}
for range_start, range_end in page_ranges:
future = _submit_pdf_render_task(
executor,
_load_images_from_pdf_worker,
pdf_bytes,
dpi,
range_start,
range_end,
image_type,
)
futures.append(future)
future_to_range[future] = range_start
_, not_done = wait(futures, timeout=timeout, return_when=ALL_COMPLETED)
if not_done:
recycle_executor = True
raise TimeoutError(
f"PDF image rendering timeout after {timeout}s "
f"for pages {start_page_id + 1}-{end_page_id + 1}"
)
all_results = []
for future in futures:
range_start = future_to_range[future]
images_list = future.result()
collected_image_lists.append(images_list)
all_results.append((range_start, images_list))
all_results.sort(key=lambda x: x[0])
images_list = []
for _, imgs in all_results:
images_list.extend(imgs)
collected_image_lists.clear()
return images_listView on GitHub (pinned to 4fe4bde114)
Solutions
- Raise the timeout parameter so it scales with page count and DPI (e.g. 30s per 50 pages as a starting heuristic), since the budget covers all ranges submitted together.
- Reduce per-page cost: lower DPI, process the document in smaller end_page_id/start_page_id chunks instead of the whole file at once.
- Give the process real resources: increase container CPU/memory limits, avoid oversubscribing the executor with unrelated work.
- If it recurs deterministically on one file, that PDF is likely corrupt/pathological — try re-saving it with qpdf or Ghostscript, or render that page range separately to isolate the culprit page.
- Retry once on a fresh process: the executor-recycling flag exists because a stuck worker often clears after a restart.
Example fix
# before
images = pdf_image_tools...render(timeout=60) # 500-page scanned book -> TimeoutError
# after
for start in range(0, n_pages, 50):
images += render_range(start, min(start + 50, n_pages), dpi=150, timeout=120) Defensive patterns
Strategy: retry
Validate before calling
n_pages = get_page_count(pdf_bytes) timeout = max(60, n_pages * 2) # scale budget with document size dpi = 150 if n_pages > 200 else 200 # reduce cost for big docs
Type guard
def render_budget_ok(n_pages: int, dpi: int, timeout: int) -> bool:
# rough heuristic: ~0.5-2s per page at 150-200 dpi with healthy workers
return timeout >= n_pages * 1.5 * (dpi / 150.0) Try / catch
for attempt in range(2):
try:
images = render_pages(pdf_bytes, start, end, dpi=dpi, timeout=timeout)
break
except TimeoutError:
if attempt == 1:
raise # executor is recycled; retry once on a fresh one, then surface
timeout *= 2 Prevention
- Scale the timeout with page count and DPI instead of using a fixed constant.
- Chunk long documents (e.g. 50 pages per call) so one slow range cannot blow the whole budget.
- Size container CPU/memory limits for parallel rendering; starving workers is the most common cause of deterministic timeouts.
- Isolate pathological PDFs: re-save suspects with qpdf/Ghostscript before processing.
When it happens
Trigger: Calling the PDF-to-image utility (mineru.utils.pdf_image_tools) with a very large or pathological PDF (hundreds/thousands of pages, huge page sizes, complex vector graphics) and the default or a low timeout; or with an executor whose workers are starved (CPU-bound competing processes, very low memory causing swapping, PyMuPDF deadlocks in forked workers).
Common situations: Batch servers processing scanned books at high DPI; containers with CPU limits where each worker gets a fraction of a core; memory exhaustion making rendering orders of magnitude slower; a hung worker from a known fork-after-import issue in the renderer.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timed out waiting for local worker {server_id} to become hea
- Unsupported middle json backend for client-side output gener
- Unknown process_mode: {process_mode}
- Unsupported office suffix: {file_suffix}
- Unsupported file type: {file_suffix}
AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14).
Data as JSON: /api/errors/530a469a85daecab.
Report an issue: GitHub.