run-llama/liteparse · error · Error
WASI proc_exit called with code
Error message
WASI proc_exit called with code ${code} What it means
During the WASM build, a post-processing script patches the generated wasm-bindgen JS glue to supply stubbed WASI imports, because the bundled PDFium build must run in a sandboxed browser with no filesystem. The stubbed `proc_exit` is not expected to ever be called; if the WASM module attempts to exit the WASI process, the stub throws this Error to surface the unexpected termination loudly instead of silently doing nothing. In practice it means the underlying C/C++ code invoked `exit()` — usually a fatal abort inside PDFium or the parser.
Solutions
- Inspect the stderr logs emitted as '[pdfium] ...' by the fd_write stub just before the throw to identify the native-side abort message
- Verify the PDF input: try the same file via the native CLI (cargo/npm/pip) to confirm whether the document itself triggers the abort
- Upgrade to the latest liteparse-wasm package — the pdfium WASM build or patch script may already handle this exit path
- If you maintain the build, extend patch-wasi-imports.js stubs (e.g. allowlist needed WASI calls) or embed a WASI runtime instead of stubs
- Catch the Error around parse calls and treat the document as unparseable in the WASM target, falling back to a server-side parse
Example fix
// before
try {
const result = await parser.parse(fileBytes, 'doc.pdf');
} catch (e) { /* unhandled: WASI proc_exit called with code 1 */ }
// after
try {
const result = await parser.parse(fileBytes, 'doc.pdf');
} catch (e) {
if (String(e).includes('proc_exit')) {
result = await parseViaServer(fileBytes); // fallback off the WASM target
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// No pre-call validation possible; optionally verify wasm asset version
const isWasmBuild = typeof WebAssembly === 'object';
if (!isWasmBuild) throw new Error('liteparse-wasm requires WebAssembly support'); Type guard
function isProcExitError(e: unknown): e is Error {
return e instanceof Error && e.message.includes('proc_exit');
} Try / catch
try {
result = await parser.parse(bytes, name);
} catch (e) {
if (isProcExitError(e)) {
console.error('Native parser aborted (proc_exit); falling back to server parse', e);
result = await parseViaServer(bytes);
} else {
throw e;
}
} Prevention
- Validate/sanitize PDF inputs (reject encrypted or known-malformed files) before the WASM parser
- Keep liteparse-wasm and its bundled pdfium build up to date
- Watch '[pdfium]' console.warn output during development to catch native aborts early
- Keep a server-side (native CLI/node binary) parse fallback for documents the WASM target cannot handle
When it happens
Trigger: Loading or calling the liteparse WASM module (LiteParse.parse and friends) when the embedded PDFium/native code calls the WASI `proc_exit` syscall, i.e. C-level `exit()` is reached. Typical causes: a fatal internal abort in PDFium while parsing a malformed or encrypted PDF, or code paths requiring preopen filesystem access that the stubs deny leading to an exit path.
Common situations: Bundling the .wasm with a PDFium build that calls exit() on unrecoverable input; running in a browser/Node environment where the patched WASI stubs replaced a full WASI runtime like wasmer/wasmoon; parsing corrupted or password-protected PDFs in the WASM target.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- USERPROFILE env var not set
- HOME env var not set
- failed to create temp dir
- failed to extract pdfium archive
- failed to move pdfium to cache dir
AI-assisted analysis of run-llama/liteparse@22d2dd8cd7 (2026-09-08).
Data as JSON: /api/errors/b2678b9c7520bdd8.
Report an issue: GitHub.
Appendix: source
Thrown at packages/wasm/scripts/patch-wasi-imports.js:90
const ptr = view.getUint32(iovs + i * 8, true);
const len = view.getUint32(iovs + i * 8 + 4, true);
// Optionally log stderr to console
if (fd === 2 && len > 0) {
try {
const text = new TextDecoder().decode(mem.subarray(ptr, ptr + len));
console.warn("[pdfium]", text);
} catch (_) {}
}
total += len;
}
view.setUint32(nwritten, total, true);
return ${ERRNO_SUCCESS};
},
path_filestat_get() { return ${ERRNO_NOENT}; },
path_open() { return ${ERRNO_NOENT}; },
path_remove_directory() { return ${ERRNO_NOSYS}; },
path_unlink_file() { return ${ERRNO_NOSYS}; },
proc_exit(code) { throw new Error("WASI proc_exit called with code " + code); },
};
const __env_stubs = {
// __c_longjmp is a WASM exception handling tag used for setjmp/longjmp.
// It must be a WebAssembly.Tag, not a function.
__c_longjmp: new WebAssembly.Tag({ parameters: ["i32"] }),
};
// --- end stubs ---
`;
// 1. Remove the top-level `import ... from "env"` and `import ... from "wasi_snapshot_preview1"`
// These are ES module imports that can't resolve in a browser.
source = source.replace(/^import \* as import\d+ from "(?:env|wasi_snapshot_preview1)";?\n/gm, "");
// 2. Inject stubs before the __wbg_get_imports function
source = source.replace(
"function __wbg_get_imports() {",
STUBS_CODE + "\nfunction __wbg_get_imports() {"View on GitHub (pinned to 22d2dd8cd7)