rust-lang/rust · critical

aborting due to `-Z treat-err-as-bug=1`

Error message

aborting due to `-Z treat-err-as-bug=1`

What it means

Emitted by panic_if_treat_err_as_bug when the -Z treat-err-as-bug=1 flag is set and rustc has just recorded exactly one error guarantee. Instead of continuing to emit the error normally, the driver aborts via panic! so compiler developers get a backtrace at the point the error is raised. This is a developer-only instrumentation of the compiler, never enabled in a normal build.

Source

Thrown at compiler/rustc_errors/src/lib.rs:1528

                    "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`"
                ).arg("level", bug.level).format();
                bug.sub(Note, msg, bug.span.primary_span().unwrap().into());
            }
            bug.level = Bug;

            self.emit_diagnostic(bug, None);
        }

        // Panic with `DelayedBugPanic` to avoid "unexpected panic" messages.
        panic::panic_any(DelayedBugPanic);
    }

    fn panic_if_treat_err_as_bug(&self) {
        if self.treat_err_as_bug() {
            let n = self.flags.treat_err_as_bug.map(|c| c.get()).unwrap();
            assert_eq!(n, self.err_guars.len() + self.lint_err_guars.len());
            if n == 1 {
                panic!("aborting due to `-Z treat-err-as-bug=1`");
            } else {
                panic!("aborting after {n} errors due to `-Z treat-err-as-bug={n}`");
            }
        }
    }
}

struct DelayedDiagInner {
    inner: DiagInner,
    note: Backtrace,
}

impl DelayedDiagInner {
    fn with_backtrace(diagnostic: DiagInner, backtrace: Backtrace) -> Self {
        DelayedDiagInner { inner: diagnostic, note: backtrace }
    }

    fn decorate(self) -> DiagInner {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Remove -Z treat-err-as-bug (and any -Z treat-err-as-bug=1) from RUSTFLAGS / config.toml / .cargo/config if you are not debugging the compiler
  2. If you are debugging: read the panic backtrace, it points at the emission site of the first error
  3. Clear cached RUSTFLAGS in shell, cargo config, and bootstrap profile after switching off the debug flag

Example fix

# before
RUSTFLAGS="-Z treat-err-as-bug=1" cargo build
# after
cargo build
Defensive patterns

Strategy: validation

Validate before calling

// This panic is triggered by the -Z treat-err-as-bug=1 unstable flag.
// Validate build configuration before invoking rustc:
fn rustc_invocation_is_safe(args: &[String]) -> Result<(), String> {
    for a in args {
        if a.starts_with("-Z") && a.contains("treat-err-as-bug") {
            return Err(format!(
                "refusing to invoke rustc with unstable flag {} (forces abort on first error)",
                a
            ));
        }
    }
    Ok(())
}

// before spawning rustc:
// rustc_invocation_is_safe(&args)?;

Type guard

// Validate that the resolved rustc profile does not enable treat-err-as-bug.
struct RustcArgs { flags: Vec<String> }

impl RustcArgs {
    fn treats_err_as_bug(&self) -> bool {
        self.flags.iter().any(|f| {
            f == "-Ztreat-err-as-bug"
            || f.starts_with("-Ztreat-err-as-bug=")
            || f.starts_with("--treat-err-as-bug")
        })
    }
}

Try / catch

// rustc aborts the process here (not a Rust Result); catch it at the
// subprocess boundary, not with try/catch in-process.
let output = std::process::Command::new("rustc")
    .args(&filtered_args)
    .output()?;

if output.status.code() == Some(134) /* SIGABRT */
    || std::str::from_utf8(&output.stderr)
        .map(|s| s.contains("treat-err-as-bug"))
        .unwrap_or(false)
{
    return Err("rustc aborted because treat-err-as-bug promoted a normal error to an abort. Remove -Z treat-err-as-bug for production builds.".into());
}

Prevention

When it happens

Trigger: rustc is invoked with -Z treat-err-as-bug=1 (or treat-err-as-bug defaults are forced on) and the diagnostic context reaches the first error-guaranteeing diagnostic. The assertion n == err_guars + lint_err_guars must hold (n == 1 here), then panic! fires the single-error message.

Common situations: A rustc contributor debugging why a particular diagnostic fires; a tool that accidentally leaves -Z treat-err-as-bug on in RUSTFLAGS; passing -Z flags on stable (rejected earlier); stale RUSTFLAGS in a project after switching toolchains.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/a8950e2a7e221107.json. Report an issue: GitHub.