run-llama/liteparse · error · ParseTimeoutError
parse of exceeded s; the worker process was killed
Error message
parse of {source} exceeded {timeout}s; the worker process was killed What it means
When a parse exceeds the pool's parse_timeout, the worker subprocess is killed and parse raises ParseTimeoutError carrying the source name and the timeout value. The pool then transparently replaces the killed worker so subsequent parses still work. This is a deliberate hard-kill design: a hung parse (e.g. inside PDFium) cannot be interrupted in-process, so the whole worker is terminated.
Solutions
- Raise parse_timeout to a value comfortably above your worst-case document parse time (or pass None to disable)
- Pre-screen inputs: skip or route oversized/complex PDFs (page count, file size) to a longer-timeout pool
- Catch ParseTimeoutError per document and continue the batch — the pool already replaced the dead worker
- Try parsing the offending file with the native CLI to determine whether it hangs deterministically; report pathological files upstream
- Run a separate pool with a larger timeout for heavy documents instead of slowing every request
Example fix
# before
pool = WorkerPool(config, pool_size=4, parse_timeout=10)
result = pool.parse(big_pdf_bytes, 'huge.pdf') # ParseTimeoutError
# after
pool = WorkerPool(config, pool_size=4, parse_timeout=120)
try:
result = pool.parse(big_pdf_bytes, 'huge.pdf')
except ParseTimeoutError as e:
log.warning('skipped %s: exceeded %ss', e.source, e.timeout)
result = None Defensive patterns
Strategy: try-catch
Validate before calling
MAX_PAGES = 2000
if os.path.getsize(path) > 500 * 1024 * 1024:
raise ValueError(f'{path} too large for default timeout pool') Type guard
from liteparse import ParseTimeoutError
def is_timeout_error(e: Exception) -> bool:
return isinstance(e, ParseTimeoutError) Try / catch
try:
result = pool.parse(data, source)
except ParseTimeoutError as e:
log.warning('parse timeout for %s after %ss', e.source, e.timeout)
result = None # or retry on a long-timeout pool Prevention
- Set parse_timeout from measured worst-case parse times, not guesses
- Route very large or scanned documents to a dedicated pool with a larger timeout
- Catch ParseTimeoutError per item in batch jobs so one bad file doesn't abort the run
- Provision headroom on CPU-constrained machines; slow hosts need larger timeouts
- Report deterministically hanging PDFs to the liteparse maintainers
When it happens
Trigger: Calling WorkerPool.parse on a document that takes longer than parse_timeout seconds — huge or pathological PDFs, PDFs with pathological content streams that hang PDFium, or a parse_timeout set too low for your document sizes (or left as a small default).
Common situations: Scanning very large scanned PDFs with OCR-heavy pages; a corrupt/malformed PDF causing PDFium to loop; setting parse_timeout=5s while real documents take 30s; batch jobs where one bad file kills its worker repeatedly.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- parse_timeout must be > 0 seconds
- parser pool is closed
- {str(e)}
- parseTimeoutMs must be > 0
- parse of exceeded ms; the worker process was killed
AI-assisted analysis of run-llama/liteparse@22d2dd8cd7 (2026-09-08).
Data as JSON: /api/errors/24e2511133fae898.
Report an issue: GitHub.
Appendix: source
Thrown at packages/python/liteparse/_pool.py:245
if worker in self._workers:
self._workers.remove(worker)
def parse(self, payload: Union[str, bytes], source: str) -> Any:
"""Run one parse on an idle worker.
Blocks until a worker is free; ``parse_timeout`` bounds the parse
itself, not the wait for a free worker.
"""
if self._closed:
raise ParseError("parser pool is closed")
worker = self._idle.get()
replace = False
try:
status, data = worker.request(payload, self._timeout)
except _WorkerTimeout:
replace = True
timeout = self._timeout
raise ParseTimeoutError(
f"parse of {source} exceeded {timeout}s; "
"the worker process was killed",
source=source,
timeout=timeout,
) from None
except _WorkerCrashed as e:
replace = True
raise ParseError(
f"liteparse worker process died while parsing {source}: {e}"
) from None
except _WorkerInitFailed as e:
replace = True
raise ParseError(f"liteparse worker failed to initialize: {e}") from None
finally:
if replace:
self._retire_worker(worker)
if not self._closed:
self._spawn_worker()View on GitHub (pinned to 22d2dd8cd7)