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
- `cargo clean` and rebuild to discard the corrupt object/archive member.
- Re-emit the offending object with the same toolchain (LLVM version) that rustc is using, or avoid feeding foreign bitcode objects into the archive.
- Inspect the message after `LLVM error:` — it is LLVM's own diagnostic and usually names the malformed record/object.
- 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
- Run cargo clean before rebuilding if you see intermittent LLVM archive errors — stale .rlib/.a artifacts from a different toolchain version are a common cause
- Verify object files are not truncated or corrupt: use file --mime-type on .o files before linking
- Ensure sufficient disk space with df -h before large archive builds — LLVM writes the archive atomically and fails if the disk fills mid-write
- Avoid concurrent cargo invocations writing to the same target/ directory — use separate CARGO_TARGET_DIR per job
- Pin a stable LLVM/rustc version for your toolchain — object format changes between major LLVM releases can cause symbol-read failures
- For bitcode-only archives (.rlib with -C lto), the error is non-fatal and can be safely ignored if your final linker uses a compatible LLVM version
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
- non-UTF8 diagnostic
- archive member at offset {start} with size {} exceeds archiv
- Architecture {arch} does not support GpuKernel calling conve
- couldn't open rlib
- wanted an rlib
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/a517b9581e14b6cb.json.
Report an issue: GitHub.