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
- Re-run `cargo clean` then rebuild with the same LTO flags so the rlib artifacts are regenerated consistently.
- Check the file/path in the panic backtrace: verify it exists (`ls -l <path>`) and is readable by the current user.
- 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.
- If running in CI/containers, confirm the `target/` directory and sysroot are on a readable filesystem and not concurrently mutated by parallel jobs.
- 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
- Run `cargo clean` before LTO builds so stale/missing rlibs are regenerated.
- Do not delete or move files out of target/ while a build is running.
- Verify CARGO_TARGET_DIR is on a mounted, readable filesystem with correct permissions.
- Pin dependency versions in Cargo.lock so expected rlib paths always exist.
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
- couldn't map rlib
- wanted an rlib
- corrupt rlib
- failed to mmap LTO bitcode file `{}`: {}
- Error writing pre-lto-bitcode file `{}`: {}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/ff649403a1a8c5d3.json.
Report an issue: GitHub.