{"id":"034ba5c597aaa8bf","repo":"rust-lang/cargo","slug":"build-script-logged-errors","errorCode":null,"errorMessage":"build script logged errors","messagePattern":"build script logged errors","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/compiler/custom_build.rs","lineNumber":671,"sourceCode":"                build_script_outputs,\n                id,\n                metadata_hash,\n                log_messages_in_case_of_panic,\n            );\n            return Err(error);\n        }\n        // ... or it logged any errors\n        else if log_messages_in_case_of_panic\n            .iter()\n            .any(|(severity, _)| *severity == Severity::Error)\n        {\n            insert_log_messages_in_build_outputs(\n                build_script_outputs,\n                id,\n                metadata_hash,\n                log_messages_in_case_of_panic,\n            );\n            anyhow::bail!(\"build script logged errors\");\n        }\n\n        let output = output.unwrap();\n\n        // After the build command has finished running, we need to be sure to\n        // remember all of its output so we can later discover precisely what it\n        // was, even if we don't run the build command again (due to freshness).\n        //\n        // This is also the location where we provide feedback into the build\n        // state informing what variables were discovered via our script as\n        // well.\n        paths::write(&run_files.stdout, &output.stdout)?;\n        // This mtime shift allows Cargo to detect if a source file was\n        // modified in the middle of the build.\n        paths::set_file_time_no_err(run_files.stdout, timestamp);\n        paths::write(&run_files.stderr, &output.stderr)?;\n        paths::write(&run_files.root_output, paths::path2bytes(&script_out_dir)?)?;\n        let parsed_output = BuildOutput::parse(","sourceCodeStart":653,"sourceCodeEnd":689,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/compiler/custom_build.rs#L653-L689","documentation":"Cargo runs a package's build.rs and streams its stdout. Any line beginning with 'cargo::error=' (legacy 'cargo:error=' unsupported, but warnings use 'cargo:warning='/'cargo::warning=') is recorded at Severity::Error. Even when the build script exits successfully (exit code 0), if at least one cargo::error= line was logged, Cargo treats the unit as failed (custom_build.rs:660-672) and bails with 'build script logged errors'. This lets build scripts emit structured errors without a non-zero exit.","triggerScenarios":"A build.rs prints a line like `println!(\"cargo::error=some message\")` (or code that does) and then exits 0. The streaming callback in exec_with_streaming pushes (Severity::Error, msg); the post-run check sees it and bails.","commonSituations":"Build script that conditionally emits cargo::error= for a missing system dependency but forgets to exit non-zero; a dependency's build script emitting cargo::error=; migrating from cargo:warning= to cargo::error= to harden a previously-soft check.","solutions":["Re-run with `cargo build -vv` (extra_verbose) to surface the exact 'cargo::error=' message the script printed.","Open the failing package's build.rs and find the `cargo::error=` emission; fix the underlying condition (install the missing system lib, set the env var, etc.).","If the error emission was unintended, change `cargo::error=` to `cargo::warning=` so it no longer fails the build, or remove the line.","Ensure the script exits non-zero on real failure instead of relying solely on cargo::error= if you want explicit exit codes."],"exampleFix":"// before (build.rs)\nprintln!(\"cargo::error=libfoo not found\");\n// after\nprintln!(\"cargo:warning=libfoo not found, using fallback\");","handlingStrategy":"validation","validationCode":"// In build.rs, gate any cargo::error= emission behind a real check and\n// prefer cargo:warning= for non-fatal conditions.\nfn require_tool(name: &str) {\n    if !std::process::Command::new(name).output().is_ok() {\n        println!(\"cargo::warning={name} not found\"); // not cargo::error=\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run builds with -vv during development to see every cargo::error=/cargo:warning= line.","Reserve cargo::error= for conditions that should always fail the build; exit non-zero for hard failures.","Audit dependency build scripts when upgrading crates that bind native libraries."],"tags":["build-script","custom-build","stdout","structured-error"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}