run-llama/liteparse · error · ParseTimeoutError

parse of exceeded ms; the worker process was killed

Error message

parse of ${source} exceeded ${this.timeoutMs}ms; the worker process was killed

What it means

When a parse on a pool worker exceeds the configured parseTimeoutMs, the pool kills the worker process and throws ParseTimeoutError with the source name and the timeout that was exceeded. The offending worker is retired, so the pool remains usable for subsequent parses. This bounds the parse itself, not the wait for a free worker.

Solutions

  1. Raise `parseTimeoutMs` to a value that accommodates your largest documents.
  2. Catch ParseTimeoutError and fall back to a longer-timeout pool or a non-pooled parse for that document.
  3. Pre-screen documents (page count/size) and route big ones to a pool with a larger timeout.
  4. Set a timeout of undefined (disable) if unbounded parses are acceptable.
  5. Investigate why the document is slow (OCR settings, page count) if most parses time out.

Example fix

// before
const pool = new WorkerPool(cfg, 2, 5000);
// after
const pool = new WorkerPool(cfg, 2, 60000);
try {
  await pool.parse(buf, 'big.pdf');
} catch (e) {
  if (e instanceof ParseTimeoutError) { /* retry with larger pool/timeout */ }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { statSync } from 'fs';
const mb = statSync(path).size / 1e6;
const timeoutMs = mb > 50 ? 120000 : 15000; // scale timeout to document size

Try / catch

import { ParseTimeoutError } from './pool.js';
try {
  result = await pool.parse(buf, source);
} catch (e) {
  if (e instanceof ParseTimeoutError) {
    result = await slowPool.parse(buf, source); // pool with larger parseTimeoutMs
  } else throw e;
}

Prevention

When it happens

Trigger: Parsing a huge or pathologically complex PDF with `parseTimeoutMs` set (e.g. 5000ms) via `pool.parse(payload, source)`; a timeout configured too aggressively for large documents; a worker stuck in native PDFium code.

Common situations: Scanned documents triggering OCR within the parse; 500+ page PDFs with a default-sized timeout; production timeouts tuned on small test files then applied to real workloads.

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/9d96c9ef6761b62a. Report an issue: GitHub.

Appendix: source

Thrown at packages/node/src/pool.ts:262

    if (!this.closed) this.spawnWorker();
  }

  /** Run one parse on an idle worker.
   *
   * Waits for a free worker first; `parseTimeoutMs` bounds the parse itself,
   * not the wait. */
  async parse(payload: string | Buffer, source: string): Promise<ParseResult> {
    if (this.closed) throw new Error("parser pool is closed");
    const worker = await this.acquire();
    try {
      await worker.ready();
      const result = await worker.request(payload, this.timeoutMs);
      this.release(worker);
      return result;
    } catch (e) {
      this.retire(worker);
      if (e instanceof WorkerTimeout) {
        throw new ParseTimeoutError(
          `parse of ${source} exceeded ${this.timeoutMs}ms; the worker process was killed`,
          source,
          this.timeoutMs!,
        );
      }
      if (e instanceof WorkerCrashed) {
        throw new Error(
          `liteparse worker process died while parsing ${source}: ${e.message}`,
        );
      }
      throw e;
    }
  }

  /** Resolves when every worker is initialized. Optional — the first parse
   * per worker waits for init anyway. */
  async warmUp(): Promise<void> {
    await Promise.all([...this.workers].map((w) => w.ready()));

View on GitHub (pinned to 22d2dd8cd7)