rust-lang/rust · error

failed to mmap LTO bitcode file `{}`: {}

Error message

failed to mmap LTO bitcode file `{}`: {}

What it means

Raised by SerializedModule::from_file in the LTO pipeline after a bitcode file was successfully opened but could not be memory-mapped. The panic happens inside Mmap::map, meaning the open() succeeded but the OS refused to map the file's bytes into the address space. rustc uses mmap here to avoid copying potentially large bitcode blobs pulled out of rlibs during fat/thin LTO.

Source

Thrown at compiler/rustc_codegen_ssa/src/back/lto.rs:61

    pub modules: Vec<SerializedModule<B::ModuleBuffer>>,
    pub module_names: Vec<CString>,
}

pub enum SerializedModule<M: ModuleBufferMethods> {
    Local(M),
    FromRlib(Vec<u8>),
    FromUncompressedFile(Mmap),
}

impl<M: ModuleBufferMethods> SerializedModule<M> {
    pub fn from_file(bc_path: &Path) -> Self {
        let file = fs::File::open(&bc_path).unwrap_or_else(|e| {
            panic!("failed to open LTO bitcode file `{}`: {}", bc_path.display(), e)
        });

        let mmap = unsafe {
            Mmap::map(file).unwrap_or_else(|e| {
                panic!("failed to mmap LTO bitcode file `{}`: {}", bc_path.display(), e)
            })
        };
        SerializedModule::FromUncompressedFile(mmap)
    }

    pub fn data(&self) -> &[u8] {
        match *self {
            SerializedModule::Local(ref m) => m.data(),
            SerializedModule::FromRlib(ref m) => m,
            SerializedModule::FromUncompressedFile(ref m) => m,
        }
    }
}

fn crate_type_allows_lto(crate_type: CrateType) -> bool {
    match crate_type {
        CrateType::Executable
        | CrateType::Dylib

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Check the underlying errno from the panic message (PermissionDenied, ENOMEM, ENODEV, etc.) and address that specifically
  2. Free address space / raise vm.overcommit or RLIMIT_AS, or move to a 64-bit toolchain
  3. Move the cargo target dir off network/odd filesystems onto a local disk that supports mmap
  4. Ensure no second build is mutating the target directory concurrently (use a unique target dir per job)
  5. Disable LTO for the failing crate (-C lto=off) if the environment cannot mmap

Example fix

# before
RUSTFLAGS="-C lto=fat" cargo build --release
# after (on a no-mmap FS / memory-tight runner)
RUSTFLAGS="-C lto=thin -C codegen-units=16" cargo build --release
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;
use std::fs;

fn ensure_lto_bitcode_readable(path: &Path) -> std::io::Result<()> {
    if !path.exists() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            format!("LTO bitcode file not found: {}", path.display()),
        ));
    }
    let meta = fs::metadata(path)?;
    if meta.len() == 0 {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidData,
            "LTO bitcode file is empty (possible truncated write)",
        ));
    }
    let file = fs::File::open(path)?;
    if file.metadata()?.permissions().readonly() {
        // mmap of read-only is fine for LTO read; only warn if write-backed mmap expected
    }
    Ok(())
}

// before invoking the LTO/back-end entry point:
// ensure_lto_bitcode_readable(&path)?;

Type guard

// mmap failure surfaces as std::io::Error; narrow on the kind rather than text.
fn is_mmap_error(e: &std::io::Error) -> bool {
    matches!(
        e.kind(),
        std::io::ErrorKind::UnexpectedEof
            | std::io::ErrorKind::InvalidData
            | std::io::ErrorKind::PermissionDenied
            | std::io::ErrorKind::OutOfMemory
    ) || e.raw_os_error().map_or(false, |c| {
        // ENOMEM, EACCES, ENOENT, EFBIG, ENODEV, EOVERFLOW
        matches!(c, 12 | 13 | 2 | 27 | 19 | 75)
    })
}

Try / catch

match lto::run(&path) {
    Ok(out) => out,
    Err(ref e) if is_mmap_error(e) => {
        // transient (NFS, tmpfs pressure) -> one bounded retry with a fresh fd
        eprintln!("warning: mmap failed for {}: {}; remapping", path.display(), e);
        lto::run(&path).expect("mmap retry failed")
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Mmap::map(file) returns Err immediately after fs::File::open succeeded, while constructing a SerializedModule for an LTO bitcode file. Concrete causes: file truncated/removed between open and mmap, mmap resource limits (RLIMIT_AS / vm.overcommit), filesystem that does not support mmap (some FUSE/NFS configs, certain network FS), file size of zero, or permission/SELinux denial on the map syscall.

Common situations: Building large crates with -C lto=fat or thin on memory-constrained CI runners; cross-compiling with bitcode stored on a network mount; /tmp mounted tmpfs with restrictive overcommit; concurrent builds mutating the same target dir; running out of address space under 32-bit toolchains.

Related errors


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