{"record":{"id":"f1909dae93f82204","repo":"rust-lang/rust","slug":"llvm-link-failed-to-link-files","errorCode":null,"errorMessage":"llvm-link failed to link files {:?}","messagePattern":"llvm-link failed to link files (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/tools/llvm-bitcode-linker/src/linker.rs","lineNumber":80,"sourceCode":"    fn link(&mut self) -> anyhow::Result<()> {\n        tracing::info!(\"Linking {} files using llvm-link\", self.files.len());\n\n        let llvm_link_output = std::process::Command::new(\"llvm-link\")\n            .arg(\"--ignore-non-bitcode\")\n            .args(&self.files)\n            .arg(\"-o\")\n            .arg(&self.link_path)\n            .output()\n            .context(\"An error occurred when calling llvm-link. Make sure the llvm-tools component is installed.\")?;\n\n        if !llvm_link_output.status.success() {\n            tracing::error!(\n                \"llvm-link returned with Exit status: {}\\n stdout: {}\\n stderr: {}\",\n                llvm_link_output.status,\n                String::from_utf8(llvm_link_output.stdout).unwrap(),\n                String::from_utf8(llvm_link_output.stderr).unwrap(),\n            );\n            anyhow::bail!(\"llvm-link failed to link files {:?}\", self.files);\n        }\n\n        Ok(())\n    }\n\n    /// Optimize and compile to native format using `opt` and `llc`\n    ///\n    /// Before this can be called `link` needs to be called\n    fn optimize(&mut self, optimization: Optimization, debug: bool) -> anyhow::Result<()> {\n        let mut passes = format!(\"default<{}>\", optimization);\n\n        // We add an internalize pass as the rust compiler as we require exported symbols to be explicitly marked\n        passes.push_str(\",internalize,globaldce\");\n        let symbol_file_content = self.symbols.iter().fold(String::new(), |s, x| s + &x + \"\\n\");\n        std::fs::write(&self.sym_path, symbol_file_content)\n            .context(format!(\"Failed to write symbol file: {}\", self.sym_path.display()))?;\n\n        tracing::info!(\"optimizing bitcode with passes: {}\", passes);","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/rust-lang/rust/blob/7088e4b63a9516ebfbfe2ab2d999cf01a528ac14/src/tools/llvm-bitcode-linker/src/linker.rs#L62-L98","documentation":"Bailed by Session::link when the external llvm-link process exits with a non-zero status. The tool invokes llvm-link --ignore-non-bitcode over all added files; failure means LLVM could not merge the bitcode (corrupt input, incompatible modules, unresolved symbols). The detailed stdout/stderr is logged at error level before the bail.","triggerScenarios":"Calling Session::lto (or link directly) after add_file with one or more bitcode/archive files, when llvm-link returns non-zero. Caused by: a non-bitcode file that --ignore-non-bitcode still rejects, mismatched LLVM bitcode versions across inputs, duplicate module definitions, or a corrupt .bc file.","commonSituations":"Mixing rlibs/bitcode produced by different rustc versions; passing an archive that contains no valid bitcode member; an LLVM upgrade that changed the bitcode format; running without the llvm-tools component (though that path fails earlier with the context message).","solutions":["Check the tracing error logs for llvm-link's stderr — it names the offending file and reason.","Rebuild all input rlibs/bitcode with the same toolchain so their LLVM versions match.","Verify each input is valid bitcode: llvm-dis <file> -o - | head, or llvm-bcanalyzer <file>.","Ensure the llvm-tools/llvm-link component is installed and on PATH and matches the rustc LLVM."],"exampleFix":"// before: generic message, logs only on tracing channel\nanyhow::bail!(\"llvm-link failed to link files {:?}\", self.files);\n\n// after: include captured stderr in the error for the caller\nlet stderr = String::from_utf8_lossy(&llvm_link_output.stderr);\nanyhow::bail!(\n    \"llvm-link failed to link {} files: {}\",\n    self.files.len(),\n    stderr.trim()\n);","handlingStrategy":"validation","validationCode":"// Before linking, verify every input is bitcode the matching LLVM accepts:\nuse std::process::Command;\nfn all_valid_bitcode(files: &[PathBuf], llvm_link: &str) -> bool {\n    files.iter().all(|f| Command::new(llvm_link)\n        .arg(\"--check\").arg(f).output().map(|o| o.status.success()).unwrap_or(false))\n}","typeGuard":"null","tryCatchPattern":"// Surface llvm-link stderr to the caller instead of swallowing it:\nmatch session.lto(opt, debug) {\n    Ok(()) => Ok(()),\n    Err(e) if e.to_string().contains(\"llvm-link failed\") => {\n        eprintln!(\"llvm-link rejected an input; ensure all bitcode is from the same LLVM\");\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Always build rlibs/bitcode inputs with the same rustc/LLVM as the linker.","Keep llvm-tools (llvm-link) on PATH and version-matched to rustc.","Validate inputs with llvm-bcanalyzer before linking."],"tags":["llvm","linker","bitcode","subprocess","llvm-bitcode-linker"],"backgroundTag":null,"analyzedSha":"7088e4b63a9516ebfbfe2ab2d999cf01a528ac14","analyzedAt":"2026-08-10T14:17:03.603Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}