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

  1. Raise parse_timeout to a value comfortably above your worst-case document parse time (or pass None to disable)
  2. Pre-screen inputs: skip or route oversized/complex PDFs (page count, file size) to a longer-timeout pool
  3. Catch ParseTimeoutError per document and continue the batch — the pool already replaced the dead worker
  4. Try parsing the offending file with the native CLI to determine whether it hangs deterministically; report pathological files upstream
  5. 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

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.

Related errors


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)