rust-lang/rust · error · io::Error

archive member at offset

Error message

archive member at offset {start} with size {} exceeds archive size {} in `{}`

What it means

Thrown during rlib/staticlib archive construction in rustc_codegen_ssa's ArArchiveBuilder::build_inner. When copying a member from a source archive (a previously built rlib), the member's byte range [start, start+file_range.1) is sliced from the memory-mapped source archive data via archive_data.get(start..end). If the range extends past the mapped data length, .get() returns None and this InvalidData error is constructed. It means the stored file_range metadata is inconsistent with the actual archive size.

Solutions

  1. Run cargo clean (or remove the affected rlib/static archive from target/ and the registry cache) and rebuild — a clean build eliminates stale/truncated files.
  2. If the archive is in the registry cache (~/.cargo/registry/), delete the specific cache entry and let cargo re-download: rm -rf ~/.cargo/registry/cache/*/offending-crate*.rlib.
  3. Check for concurrent build processes writing to the same target/ directory and serialize them.
  4. Run file/objdump/ar t on the suspect archive to verify its integrity and member table consistency.
  5. If the archive is a native static library (.a) provided externally, obtain a fresh copy from the upstream source.

Example fix

# before: stale or corrupt rlib causing the range mismatch
cargo build  # fails with 'archive member at offset ...'
# after: clean and rebuild
cargo clean && cargo build
Defensive patterns

Strategy: try-catch

Validate before calling

// Before building, verify the integrity of source archives (rlibs).
use std::fs;
use std::path::Path;

fn verify_archive_integrity(path: &Path) -> Result<(), String> {
    let metadata = fs::metadata(path).map_err(|e| format!("cannot stat {}: {}", path.display(), e))?;
    if metadata.len() == 0 {
        return Err(format!("archive {} is empty (0 bytes)", path.display()));
    }
    // Optionally parse with the `object` crate to check member offsets
    let data = fs::read(path).map_err(|e| format!("cannot read {}: {}", path.display(), e))?;
    let archive = object::read::archive::ArchiveFile::parse(&data)
        .map_err(|e| format!("archive {} is malformed: {}", path.display(), e))?;
    for member in archive.members() {
        let member = member.map_err(|e| format!("bad member in {}: {}", path.display(), e))?;
        let _ = member.data(&data).map_err(|e| format!("member data out of bounds in {}: {}", path.display(), e))?;
    }
    Ok(())
}

Try / catch

// The archive build error surfaces as a rustc fatal diagnostic (ArchiveBuildFailure).
// There is no Rust-level try-catch; the compiler aborts. Prevent it by:
// 1. Cleaning the build: cargo clean
// 2. Re-downloading corrupt registry rlibs
// The error propagates from ArArchiveBuilder::build -> sess.dcx().emit_fatal
// which terminates compilation. Handle it operationally, not in code.

Prevention

When it happens

Trigger: Compiling a crate that links against (rlib dep or native static lib) an archive file whose internal member offsets and sizes do not match its actual byte length. The archive_index and file_range were recorded when the source archive was parsed (add_archive / add_rlib / add_native_library), but the underlying file was subsequently truncated, replaced, or corrupted before build_inner reads the member data.

Common situations: Concurrent build processes modifying the same rlib; a corrupted or partially downloaded crate registry cache; disk/filesystem corruption; an upstream bug in the object or archive crate that miscalculates member offsets; stale archive from an interrupted previous build that was not cleaned.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/606387cc14a2d854. Report an issue: GitHub.

Appendix: source

Thrown at compiler/rustc_codegen_ssa/src/back/archive.rs:623

            }
            Some((names, rename_suffix))
        } else {
            None
        };

        let mut entries = Vec::new();

        for (entry_name, entry) in self.entries {
            let data: Box<dyn AsRef<[u8]>> = match entry.source {
                ArchiveEntrySource::Archive { archive_index, file_range } => {
                    let src_archive = &self.src_archives[archive_index];
                    let archive_data = &src_archive.1;
                    let start = file_range.0 as usize;
                    let end = start + file_range.1 as usize;
                    let Some(data) = archive_data.get(start..end) else {
                        return Err(io_error_context(
                            "invalid archive member",
                            io::Error::new(
                                io::ErrorKind::InvalidData,
                                format!(
                                    "archive member at offset {start} with size {} \
                                         exceeds archive size {} in `{}`",
                                    file_range.1,
                                    archive_data.len(),
                                    src_archive.0.display(),
                                ),
                            ),
                        ));
                    };

                    if entry.kind == ArchiveEntryKind::RustObj
                        && let Some(sym) = &symbols
                    {
                        Box::new(apply_edits(data, &sym.exported, sym.hide, rename.as_ref()))
                    } else {
                        Box::new(data)

View on GitHub (pinned to 7088e4b63a)