rust-lang/rust · critical

couldn't open rlib

Error message

couldn't open rlib

What it means

Thrown by an `.expect("couldn't open rlib")` on `std::fs::File::open(&path)` in `with_symbols_below_threshold` (lto.rs:96) while loading upstream dependency rlib bitcode for fat/thin LTO. The operating system refused to open the rlib file at the recorded path, so the compiler aborts (panics) before it can mmap and parse the archive. Because LTO reads every upstream rlib on disk, this surfaces as an Internal-Compiler-Error-style crash during the link/codegen phase rather than a normal diagnostic.

Source

Thrown at compiler/rustc_codegen_llvm/src/back/lto.rs:96

    // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
    // __llvm_profile_runtime, therefore we won't know until link time if this symbol
    // should have default visibility.
    symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned());

    // LTO seems to discard this otherwise under certain circumstances.
    symbols_below_threshold.push(c"rust_eh_personality".to_owned());

    // If we're performing LTO for the entire crate graph, then for each of our
    // upstream dependencies, find the corresponding rlib and load the bitcode
    // from the archive.
    //
    // We save off all the bytecode and LLVM module ids for later processing
    // with either fat or thin LTO
    let mut upstream_modules = Vec::new();
    for path in each_linked_rlib_for_lto {
        let archive_data = unsafe {
            Mmap::map(std::fs::File::open(&path).expect("couldn't open rlib"))
                .expect("couldn't map rlib")
        };
        let archive = ArchiveFile::parse(&*archive_data).expect("wanted an rlib");
        let metadata_link = rmeta_link::read(&archive, &archive_data, &path).unwrap();
        let obj_files = archive
            .members()
            .filter_map(|child| {
                child
                    .ok()
                    .and_then(|c| std::str::from_utf8(c.name()).ok().map(|name| (name.trim(), c)))
            })
            .filter(|&(name, _)| metadata_link.rust_object_files.iter().any(|f| f == name));
        for (name, child) in obj_files {
            info!("adding bitcode from {}", name);
            match get_bitcode_slice_from_object_data(
                child.data(&*archive_data).expect("corrupt rlib"),
                cgcx,
            ) {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Re-run `cargo clean` then rebuild with the same LTO flags so the rlib artifacts are regenerated consistently.
  2. Check the file/path in the panic backtrace: verify it exists (`ls -l <path>`) and is readable by the current user.
  3. Ensure the toolchain is not mid-switch (`rustup show`, `rust-toolchain.toml`) and that `--sysroot` points at an installed toolchain whose lib rlibs are intact.
  4. If running in CI/containers, confirm the `target/` directory and sysroot are on a readable filesystem and not concurrently mutated by parallel jobs.
  5. Disable LTO (`-C lto=off` / remove `lto` from `[profile.release]`) to confirm the rlib open is LTO-specific, then re-enable once artifacts are stable.

Example fix

# before: intermittent LTO crash with stale target dir
cargo build --release  # (lto=true in profile) -> panic: couldn't open rlib

# after: clean and rebuild so LTO reads fresh, consistent rlibs
cargo clean
cargo build --release
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_rlib_openable(path: &std::path::Path) -> std::io::Result<()> {
    let _f = std::fs::File::open(path)?;
    std::fs::metadata(path)?;
    Ok(())
}
// Call before invoking LTO: ensure_rlib_openable(&rlib_path)?;

Try / catch

let r = std::panic::catch_unwind(|| invoke_lto());
if r.is_err() { /* path missing -> clean target dir, restore dep, rebuild */ }

Prevention

When it happens

Trigger: Triggered only when `-C lto=thin|fat` (or `-C lto=y`) is set AND the compiler iterates `each_linked_rlib_for_lto` to load a dependency's rlib whose path cannot be opened: file deleted mid-build, wrong `--sysroot`, relocated target dir, read permission denied, or a stale `Cargo.lock`/build cache pointing at a missing artifact.

Common situations: Running `cargo clean` (or `rm -rf target`) concurrently with a second build invoking LTO; switching toolchains so `--sysroot` rlibs no longer match; read-only container/CI filesystem lacking permissions to the rlib; interrupted previous build leaving `target` half-populated; vendored rlib moved out from its recorded path.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/ff649403a1a8c5d3.json. Report an issue: GitHub.