{"id":"a517b9581e14b6cb","repo":"rust-lang/rust","slug":"llvm-error","errorCode":null,"errorMessage":"LLVM error: {}","messagePattern":"LLVM error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_llvm/src/back/archive.rs","lineNumber":85,"sourceCode":"            // We don't have access to the DiagCtxt here to produce a nice warning in the correct format.\n            eprintln!(\"warning: Failed to read symbol table from LLVM bitcode: {}\", error);\n            return Ok(true);\n        } else {\n            return Err(error);\n        }\n    }\n\n    unsafe extern \"C\" fn callback(state: *mut c_void, symbol_name: *const c_char) -> *mut c_void {\n        let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };\n        match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {\n            Ok(()) => std::ptr::null_mut(),\n            Err(err) => Box::into_raw(Box::new(err) as Box<io::Error>) as *mut c_void,\n        }\n    }\n\n    unsafe extern \"C\" fn error_callback(error: *const c_char) -> *mut c_void {\n        let error = unsafe { CStr::from_ptr(error) };\n        Box::into_raw(Box::new(io::Error::new(\n            io::ErrorKind::Other,\n            format!(\"LLVM error: {}\", error.to_string_lossy()),\n        )) as Box<io::Error>) as *mut c_void\n    }\n}\n\nfn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {\n    unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }\n}\n\nfn llvm_is_ec_object_file(buf: &[u8]) -> bool {\n    unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }\n}\n\nfn llvm_is_any_arm64_coff(buf: &[u8]) -> bool {\n    unsafe { llvm::LLVMRustIsAnyArm64Coff(buf.as_ptr(), buf.len()) }\n}\n","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_codegen_llvm/src/back/archive.rs#L67-L103","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate object files before archive creation to prevent LLVM symbol-read failures\nuse std::path::Path;\nuse std::fs;\n\nfn validate_object_files(objects: &[&str]) -> Result<(), String> {\n    for obj in objects {\n        let path = Path::new(obj);\n        let metadata = fs::metadata(path)\n            .map_err(|e| format!(\"Cannot stat {}: {}\", obj, e))?;\n        if metadata.len() == 0 {\n            return Err(format!(\"Object file {} is empty\", obj));\n        }\n        // Read magic bytes to verify it is a valid object or bitcode file\n        let mut buf = [0u8; 4];\n        use std::io::Read;\n        let mut f = fs::File::open(path)\n            .map_err(|e| format!(\"Cannot open {}: {}\", obj, e))?;\n        f.read_exact(&mut buf)\n            .map_err(|e| format!(\"Cannot read header of {}: {}\", obj, e))?;\n        let is_elf = &buf[..4] == b\"\\x7fELF\";\n        let is_coff = matches!(buf[0], 0x4d | 0x64) && matches!(buf[1], 0x5a | 0x83);\n        let is_bitcode = &buf == b\"BC\\xc0\\xde\" || &buf == &[0xDE, 0xCE, 0x17, 0x0B];\n        let is_macho = matches!(buf[0], 0xFE | 0xCF | 0xCE) || buf[0] == 0xCA;\n        if !(is_elf || is_coff || is_bitcode || is_macho) {\n            return Err(format!(\"{} is not a recognized object/bitcode file (magic: {:?})\", obj, buf));\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"// The LLVM archive error surfaces as io::Error via get_llvm_object_symbols callback.\n// Catch it at the linking/archive step:\nuse std::io;\n\nfn build_archive(objects: &[String], output: &str) -> Result<(), String> {\n    // rustc_codegn_ssa returns io::Result from archive building\n    match archive_write(objects, output) {\n        Ok(()) => Ok(()),\n        Err(ref e) if e.to_string().contains(\"LLVM error\") => {\n            // The LLVM symbol reader failed. Common causes:\n            // - corrupted or truncated object file\n            // - object produced by a newer LLVM version\n            // - disk full during archive write\n            eprintln!(\"LLVM archive error: {}\", e);\n\n            // For bitcode files, LLVM errors are non-fatal (the linker may handle them)\n            // For other object types, clean up the partial archive and retry\n            let _ = std::fs::remove_file(output);\n\n            // Retry with verbose diagnostics\n            match archive_write(objects, output) {\n                Ok(()) => Ok(()),\n                Err(e2) => Err(format!(\n                    \"Archive write failed after retry: {}. \\\n                     Run cargo clean and rebuild.\",\n                    e2\n                )),\n            }\n        }\n        Err(e) => Err(e.to_string()),\n    }\n}\n\n// Placeholder for the actual archive builder call\nfn archive_write(_objects: &[String], _output: &str) -> Result<(), io::Error> {\n    Ok(())\n}","preventionTips":["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"],"tags":["rustc-codegen-llvm","archive","rlib","llvm","linker","io-error"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}