rust-lang/cargo · error · anyhow::Error

warnings are denied by `build.warnings` configuration

Error message

warnings are denied by `build.warnings` configuration

What it means

When `build.warnings = "deny"` is set in cargo configuration, any compile/build operation that emits even one warning (counted from both the parse pass and the actual compilation) is turned into a hard failure. After `compile_ws` returns, `compile_with_exec` checks `warning_handling() == Deny` and, if the combined warning count is non-zero, bails with this message.

Source

Thrown at src/ops/cargo_compile/mod.rs:154

/// Like [`compile`] but allows specifying a custom [`Executor`]
/// that will be able to intercept build calls and add custom logic.
///
/// [`compile`] uses [`DefaultExecutor`] which just passes calls through.
pub fn compile_with_exec<'a>(
    ws: &Workspace<'a>,
    options: &CompileOptions,
    exec: &Arc<dyn Executor>,
) -> CargoResult<Compilation<'a>> {
    let parse_pass_output = crate::diagnostics::passes::emit_parse_diagnostics(
        ws,
        crate::diagnostics::rules::PARSE_PASS_RULES,
    )?;
    let compilation = compile_ws(ws, options, exec)?;
    if ws.gctx().warning_handling()? == WarningHandling::Deny
        && (compilation.lint_warning_count + parse_pass_output.lint_warning_count) > 0
    {
        anyhow::bail!("warnings are denied by `build.warnings` configuration")
    }
    Ok(compilation)
}

/// Like [`compile_with_exec`] but without warnings from manifest parsing.
#[tracing::instrument(skip_all)]
fn compile_ws<'a>(
    ws: &Workspace<'a>,
    options: &CompileOptions,
    exec: &Arc<dyn Executor>,
) -> CargoResult<Compilation<'a>> {
    let interner = UnitInterner::new();
    let logger = BuildLogger::maybe_new(ws, &options.build_config)?;

    if let Some(ref logger) = logger {
        let rustc = ws.gctx().load_global_rustc(Some(ws))?;
        let num_cpus = std::thread::available_parallelism()
            .ok()

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Fix the underlying warning(s) — the build output preceding the error lists each one; address them in source or manifest.
  2. Temporarily relax the policy by setting `warnings = "warn"` (or removing the key) in `[build]` for the offending profile.
  3. For a one-off, run with the warning allowed, e.g. via an override config or `--config` flag, then restore `deny`.

Example fix

# before (.cargo/config.toml)
[build]
warnings = "deny"
# build fails on any warning

# after (fix the warning, or relax)
[build]
warnings = "warn"
Defensive patterns

Strategy: validation

Validate before calling

// If build.warnings = "deny", ensure zero warnings before committing/building in CI.
// Run a lint pass first and count warnings:
//   cargo build 2> warnings.txt
//   if [ -s warnings.txt ]; then exit 1; fi
// Equivalent: gate on `cargo clippy -- -D warnings` before the deny-enabled build.

Try / catch

// Differentiate deny-induced failures from real compile errors by checking the config.
let handling = ws.gctx().warning_handling()?;
match ops::compile_with_exec(&ws, &opts, &exec) {
    Ok(_) => Ok(()),
    Err(e) if handling == WarningHandling::Deny && e.to_string().contains("warnings are denied") => {
        eprintln!("build aborted due to denied warnings; fix warnings or relax build.warnings");
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Building with `[build] warnings = "deny"` (or the equivalent config/env) while the code or manifest produces warnings — e.g. unused imports, deprecated API usage, or manifest lint warnings.

Common situations: Strict CI configs that enforce zero-warning builds; a dependency upgrade or refactor that introduces new warnings; manifest parse warnings from deprecated fields.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/7e3b52597eb2a200.json. Report an issue: GitHub.