rust-lang/rust · error

LLVM error: {}

Error message

LLVM error: {}

What it means

Produced by the `error_callback` registered with `LLVMRustGetSymbols` in `get_llvm_object_symbols`. When LLVM's archive/object reader cannot enumerate symbols from an object/bitcode member, it invokes this C callback with a `*const c_char` message; the callback wraps it as `io::Error::new(io::ErrorKind::Other, format!("LLVM error: {}"))`. The error then propagates out of archive (rlib/staticlib) member scanning.

Source

Thrown at compiler/rustc_codegen_llvm/src/back/archive.rs:85

            // We don't have access to the DiagCtxt here to produce a nice warning in the correct format.
            eprintln!("warning: Failed to read symbol table from LLVM bitcode: {}", error);
            return Ok(true);
        } else {
            return Err(error);
        }
    }

    unsafe extern "C" fn callback(state: *mut c_void, symbol_name: *const c_char) -> *mut c_void {
        let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
        match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
            Ok(()) => std::ptr::null_mut(),
            Err(err) => Box::into_raw(Box::new(err) as Box<io::Error>) as *mut c_void,
        }
    }

    unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
        let error = unsafe { CStr::from_ptr(error) };
        Box::into_raw(Box::new(io::Error::new(
            io::ErrorKind::Other,
            format!("LLVM error: {}", error.to_string_lossy()),
        )) as Box<io::Error>) as *mut c_void
    }
}

fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
    unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }
}

fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
    unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
}

fn llvm_is_any_arm64_coff(buf: &[u8]) -> bool {
    unsafe { llvm::LLVMRustIsAnyArm64Coff(buf.as_ptr(), buf.len()) }
}

View on GitHub (pinned to 22057b88b0)

Solutions

  1. `cargo clean` and rebuild to discard the corrupt object/archive member.
  2. Re-emit the offending object with the same toolchain (LLVM version) that rustc is using, or avoid feeding foreign bitcode objects into the archive.
  3. Inspect the message after `LLVM error:` — it is LLVM's own diagnostic and usually names the malformed record/object.
  4. If the input is legitimately newer-version bitcode, link with a newer linker (lld/mold/wild) as the code comment suggests, or upgrade rustc to one bundling a matching LLVM.
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate object files before archive creation to prevent LLVM symbol-read failures
use std::path::Path;
use std::fs;

fn validate_object_files(objects: &[&str]) -> Result<(), String> {
    for obj in objects {
        let path = Path::new(obj);
        let metadata = fs::metadata(path)
            .map_err(|e| format!("Cannot stat {}: {}", obj, e))?;
        if metadata.len() == 0 {
            return Err(format!("Object file {} is empty", obj));
        }
        // Read magic bytes to verify it is a valid object or bitcode file
        let mut buf = [0u8; 4];
        use std::io::Read;
        let mut f = fs::File::open(path)
            .map_err(|e| format!("Cannot open {}: {}", obj, e))?;
        f.read_exact(&mut buf)
            .map_err(|e| format!("Cannot read header of {}: {}", obj, e))?;
        let is_elf = &buf[..4] == b"\x7fELF";
        let is_coff = matches!(buf[0], 0x4d | 0x64) && matches!(buf[1], 0x5a | 0x83);
        let is_bitcode = &buf == b"BC\xc0\xde" || &buf == &[0xDE, 0xCE, 0x17, 0x0B];
        let is_macho = matches!(buf[0], 0xFE | 0xCF | 0xCE) || buf[0] == 0xCA;
        if !(is_elf || is_coff || is_bitcode || is_macho) {
            return Err(format!("{} is not a recognized object/bitcode file (magic: {:?})", obj, buf));
        }
    }
    Ok(())
}

Try / catch

// The LLVM archive error surfaces as io::Error via get_llvm_object_symbols callback.
// Catch it at the linking/archive step:
use std::io;

fn build_archive(objects: &[String], output: &str) -> Result<(), String> {
    // rustc_codegn_ssa returns io::Result from archive building
    match archive_write(objects, output) {
        Ok(()) => Ok(()),
        Err(ref e) if e.to_string().contains("LLVM error") => {
            // The LLVM symbol reader failed. Common causes:
            // - corrupted or truncated object file
            // - object produced by a newer LLVM version
            // - disk full during archive write
            eprintln!("LLVM archive error: {}", e);

            // For bitcode files, LLVM errors are non-fatal (the linker may handle them)
            // For other object types, clean up the partial archive and retry
            let _ = std::fs::remove_file(output);

            // Retry with verbose diagnostics
            match archive_write(objects, output) {
                Ok(()) => Ok(()),
                Err(e2) => Err(format!(
                    "Archive write failed after retry: {}. \
                     Run cargo clean and rebuild.",
                    e2
                )),
            }
        }
        Err(e) => Err(e.to_string()),
    }
}

// Placeholder for the actual archive builder call
fn archive_write(_objects: &[String], _output: &str) -> Result<(), io::Error> {
    Ok(())
}

Prevention

When it happens

Trigger: Building an `rlib`/`staticlib`/`dylib` whose dependency closure includes a malformed or unrecognized object file or LLVM bitcode member; `LLVMRustGetSymbols` fails and the formatted message (LLVM's own diagnostic) is surfaced. Note: pure LLVM bitcode magic (`0xDE,0xCE,0x17,0x0B` or `BCーC0DE`) is downgraded to a non-fatal warning on a separate path, so this error is for non-bitcode failures.

Common situations: Linking against an object produced by a newer LLVM than rustc's bundled LLVM (different bitcode wrapper), a truncated/corrupt `.o`/`.a` in the build cache, mixed COFF bigobj / EC object quirks, or stale artifacts after an interrupted build.

Related errors


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