run-llama/liteparse · error · ParseError
{data}
Error message
{data} What it means
Raised when the worker completed the request but reported a non-ok status: the message is the verbatim '{ExceptionType}: {detail}' string produced inside the worker when native parsing raised. This is the normal channel for in-process parse failures (corrupt PDFs, unsupported files, native errors) when using the pool — the actual exception type is flattened into a string inside ParseError.
Solutions
- Read the leading type name in the message (e.g. 'FileNotFoundError: ...') — it is the native exception flattened to a string
- If it is a missing converter, install the external tool (e.g. LibreOffice) on the machine running the workers
- If it is a corrupt/encrypted PDF, validate or decrypt the document before parsing
- Confirm the file path is absolute and readable from the worker process (the worker parses the path independently)
- If the message hides too much detail, run once without pool_size to get the full native traceback
Example fix
# before
parser = LiteParse(pool_size=2)
result = parser.parse("doc.docx") # ParseError: IOException: soffice not found
# after
# install the converter first, e.g.: apt-get install -y libreoffice
import shutil
assert shutil.which("soffice"), "LibreOffice required for office formats"
result = LiteParse(pool_size=2).parse("doc.docx") Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
def assert_parsable_input(file_data) -> None:
if isinstance(file_data, str):
p = Path(file_data)
if not p.is_file():
raise FileNotFoundError(p)
if p.suffix.lower() in {".docx", ".xlsx", ".pptx"} and not shutil.which("soffice"):
raise RuntimeError("LibreOffice (soffice) required for office formats") Try / catch
from liteparse.types import ParseError
try:
result = parser.parse(path)
except ParseError as e:
# message is 'ExceptionType: detail' from the worker
kind, _, detail = str(e).partition(": ")
log.error("parse failed (%s): %s", kind, detail)
raise Prevention
- Parse the message prefix to recover the original exception type
- Install external converters (LibreOffice) wherever workers run
- Pre-validate PDFs (not encrypted, correct magic bytes) before parsing
- Debug inscrutable messages by running the same input without pool_size for a full traceback
When it happens
Trigger: Any parse() / parse_bytes() call on a pooled LiteParse where native.parse() or native.parse_bytes() raises inside the worker: malformed/encrypted PDF, file path unreadable by the worker, unsupported format, conversion tool (LibreOffice) missing, etc.
Common situations: Passing an encrypted or corrupt PDF; pointing at a path that exists for the parent but not in the worker's context; DOCX/XLSX conversion failing because LibreOffice is not installed; anything that would throw the underlying native exception without a pool.
Related errors
- parse of exceeded ms; the worker process was killed
- liteparse worker process died while parsing
- parseTimeoutMs requires poolSize
- poolSize must be an integer >= 1
- parseTimeoutMs must be > 0
AI-assisted analysis of run-llama/liteparse@22d2dd8cd7 (2026-09-08).
Data as JSON: /api/errors/1dba2983ac950b05.
Report an issue: GitHub.
Appendix: source
Thrown at packages/python/liteparse/_pool.py:270
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()
elif self._closed:
worker.stop()
else:
self._idle.put(worker)
if status == "ok":
return data
raise ParseError(data)
def warm_up(self) -> None:
"""Block until every worker has finished initializing.
Optional — the first parse per worker waits for init anyway. Useful
before latency-sensitive traffic or benchmarks.
"""
workers = list(self._workers)
for worker in workers:
worker._ensure_ready()
def close(self) -> None:
"""Shut down all workers. Idempotent."""
if self._closed:
return
self._closed = True
# Stop the workers we can grab; busy workers are stopped by parse()'s
# finally-block when they come back (see the _closed check there).View on GitHub (pinned to 22d2dd8cd7)