run-llama/liteparse · critical
failed to load pdfium shared library
Error message
failed to load pdfium shared library
What it means
`Library::init()` acquires the process-wide PDFium lock and initializes PDFium, but first loads the shared library via `pdfium_sys::dynamic::load_default()`. When no loadable libpdfium can be found, `try_init()` returns `PdfiumError::LibraryUnavailable` and `init()` panics with this message. It means the pdfium shared library is missing, corrupt, or its dependencies cannot be resolved on this machine.
Solutions
- Set the PDFIUM_LIB_PATH env var to the directory containing the pdfium shared library (libpdfium.so / libpdfium.dylib / pdfium.dll) and retry.
- Download the matching pdfium binary distribution for your platform (or use the build-script download path) and place it in one of the searched locations.
- In panic-sensitive hosts (Node addon, FFI boundary), call `Library::try_init()` instead of `Library::init()` and handle `PdfiumError::LibraryUnavailable` gracefully.
- If the file exists but still fails, run `ldd`/`otool -L` on the library to find missing transitive dependencies and install them, and confirm the architecture matches your build target.
Example fix
// before
let lib = Library::init(); // panics: failed to load pdfium shared library
// after (or: export PDFIUM_LIB_PATH=/opt/pdfium/lib before running)
let lib = Library::try_init().map_err(|e| {
eprintln!("pdfium unavailable: {e:?}; set PDFIUM_LIB_PATH to the lib dir");
e
})?; Defensive patterns
Strategy: fallback
Validate before calling
// check availability without panicking
match Library::try_init() {
Ok(lib) => { /* proceed */ }
Err(PdfiumError::LibraryUnavailable) => {
eprintln!("pdfium missing; set PDFIUM_LIB_PATH to the dir containing libpdfium.so");
}
Err(e) => { /* other error */ }
} Type guard
// Rust has no runtime type guard here; narrow via the typed error enum
fn is_library_unavailable(e: &PdfiumError) -> bool {
matches!(e, PdfiumError::LibraryUnavailable)
} Try / catch
// avoid init()'s panic; use try_init and handle the error
let lib = Library::try_init()
.map_err(|e| anyhow!("pdfium shared library unavailable: {e:?}. Set PDFIUM_LIB_PATH."))?; Prevention
- Set PDFIUM_LIB_PATH in Docker images/CI so load_default() always finds the library
- Download/bundle the platform-matching pdfium shared library as part of setup
- In FFI hosts (Node addons), always use try_init() — an escaping panic aborts the process
- Verify the library loads in CI smoke tests (ldd/otool for missing transitive deps and arch mismatch)
When it happens
Trigger: Calling `Library::init()` (or anything that triggers it, e.g. `Document` loading) on a machine where `load_default()` fails: PDFIUM_LIB_PATH unset and no downloaded/cached/system libpdfium present; the library exists but has unresolved native dependencies (e.g. missing glibc/libjpeg on Linux); wrong architecture (x86_64 binary trying to load arm64 pdfium).
Common situations: Deploying to a slim Docker image or fresh CI machine without downloading the pdfium binary; PDFium downloaded for a different OS/arch; a Node addon host where the native pdfium library was not bundled; cross-platform distribution where the shared library was not shipped next to the executable.
Related errors
- pdfium not loaded — call…
- Unable to generate bindings
- no data on stdin (input `-` expects a document piped in…
- no data on stdin (input `-` expects a document piped in…
- invalid zero-sized RGB image
AI-assisted analysis of run-llama/liteparse@22d2dd8cd7 (2026-09-08).
Data as JSON: /api/errors/f9b3e89a8e2f161d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pdfium/src/library.rs:69
/// // `lib` was dropped above — using `doc` here is a use-after-unlock.
/// let _ = doc.page_count();
/// ```
pub struct Library {
#[cfg(not(target_arch = "wasm32"))]
_guard: MutexGuard<'static, ()>,
#[cfg(target_arch = "wasm32")]
_private: (),
}
impl Library {
/// Acquire the process-wide PDFium lock, blocking the current thread
/// until any other in-flight PDFium work has finished. Initializes the
/// library on first call.
///
/// Multiple concurrent callers are serialized; only one `Library`
/// instance exists at a time.
pub fn init() -> Library {
Self::try_init().expect("failed to load pdfium shared library")
}
/// [`Library::init`] that reports a missing or unloadable pdfium shared
/// library as [`PdfiumError::LibraryUnavailable`] instead of panicking.
/// Hosts that cannot afford a panic across an FFI boundary (a Node addon,
/// where an escaping panic aborts the process) should call this first;
/// the search path is described on `pdfium_sys::dynamic::load_default`.
pub fn try_init() -> Result<Library, PdfiumError> {
#[cfg(not(target_arch = "wasm32"))]
{
pdfium_sys::dynamic::load_default().map_err(|_| PdfiumError::LibraryUnavailable)?;
// Recover from poisoning: a panic mid-FFI may leave PDFium in
// an odd state, but subsequent calls should still be allowed
// (the worst case is that the next parse also fails cleanly).
let guard = pdfium_lock()
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner());
INIT.call_once(|| unsafe { ffi!(FPDF_InitLibrary()) });View on GitHub (pinned to 22d2dd8cd7)