run-llama/liteparse · error

failed to move pdfium to cache dir

Error message

failed to move pdfium to cache dir

What it means

After a successful extraction, download_pdfium atomically renames the .tmp directory into its final cache location with fs::rename, panicking with this message if the rename fails. fs::rename fails across filesystem boundaries (EXDEV) or when the destination exists as something rename cannot replace (e.g. a file, or a directory that couldn't be removed).

Solutions

  1. Remove the conflicting path in the cache dir (the dest location) and rebuild.
  2. Avoid concurrent cargo builds sharing the same cache on first download; run one build first or pre-populate the cache.
  3. Ensure the cache dir is not a cross-filesystem symlink/mount that breaks atomic rename.
  4. Check permissions so remove_dir_all(dest) can actually clear an existing stale entry.

Example fix

# before: cache dest is a stale file on a mounted volume
$ cargo build
   ... panicked: failed to move pdfium to cache dir

# after: clear the conflicting cache entry and retry serially
$ rm -rf ~/.cache/liteparse/pdfium*
$ cargo build  # single build, no parallel races
Defensive patterns

Strategy: validation

Validate before calling

# Preflight: cache dest must not be a cross-device symlink and must be clearable
CACHE="$HOME/.cache/liteparse"
[ ! -L "$CACHE" ] || { echo "cache is a symlink to another fs"; exit 1; }
[ ! -e "$CACHE/pdfium" ] || [ -d "$CACHE/pdfium" ] || { echo "stale file at cache dest"; exit 1; }

Prevention

When it happens

Trigger: Running `cargo build` where the pdfium cache dest path exists as a file (or a directory that fs::remove_dir_all silently failed to delete), or where dest and tmp end up on different mount points/filesystems (e.g. cache dir is a symlink into another mount).

Common situations: Cache dirs symlinked to another volume/mount; concurrent builds racing on the same cache path where one build removes dest while another renames; permissions preventing removal of the existing dest; corrupted cache containing a file named like the expected directory.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of run-llama/liteparse@22d2dd8cd7 (2026-09-08). Data as JSON: /api/errors/48053d1860c3d909. Report an issue: GitHub.

Appendix: source

Thrown at crates/pdfium-sys/build.rs:197

    // Extract to a temp dir first, then rename atomically
    let tmp = dest.with_extension("tmp");
    if tmp.exists() {
        fs::remove_dir_all(&tmp).ok();
    }
    fs::create_dir_all(&tmp).expect("failed to create temp dir");
    archive
        .unpack(&tmp)
        .expect("failed to extract pdfium archive");

    // Fix dylib install name on macOS so @rpath resolution works
    fix_dylib_install_name(&tmp);

    // Atomic rename into place
    if dest.exists() {
        fs::remove_dir_all(dest).ok();
    }
    fs::rename(&tmp, dest).expect("failed to move pdfium to cache dir");

    eprintln!("pdfium-sys: cached pdfium at {}", dest.display());
}

/// On macOS, pdfium-binaries ships dylibs with install name `./libpdfium.dylib`.
/// We need `@rpath/libpdfium.dylib` for rpath resolution to work.
fn fix_dylib_install_name(dir: &Path) {
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
    if target_os != "macos" {
        return;
    }

    let dylib = dir.join("lib/libpdfium.dylib");
    if !dylib.exists() {
        return;
    }

    let status = Command::new("install_name_tool")

View on GitHub (pinned to 22d2dd8cd7)