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

`rustfmt` failed

Error message

`rustfmt` failed

What it means

Returned by format_files when the underlying rustfmt subprocess exits non-zero. The wrapper deliberately suppresses the verbose command ("repeating the command is too much") and replaces any error with this short message via map_err.

Source

Thrown at src/tools/miri/miri-script/src/util.rs:296

            );
            if first {
                // Log an abbreviating command, and only once.
                eprintln!("$ {cmd} ...");
                first = false;
            }
            // Add files.
            for file in batch {
                // Make it a relative path so that on platforms with extremely tight argument
                // limits (like Windows), we become immune to someone cloning the repo
                // 50 directories deep.
                let file = file?;
                let file = file.strip_prefix(&self.miri_dir)?;
                cmd = cmd.arg(file);
            }

            // Run rustfmt.
            // We want our own error message, repeating the command is too much.
            cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?;
        }

        Ok(())
    }
}

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Re-run the rustfmt command manually without .quiet() to see the real diagnostic — drop the map_err to surface the underlying io::Error.
  2. Fix any syntax error in the offending file first.
  3. Make sure the +{toolchain} rustfmt is a nightly that supports the configured unstable features.
  4. Align rustfmt.toml options with the installed rustfmt version.

Example fix

// before: error is swallowed into a generic string
cmd.quiet().run().map_err(|_| anyhow!("`rustfmt` failed"))?;

// after: keep the command terse in logs but preserve the cause
match cmd.quiet().run() {
    Ok(()) => Ok(()),
    Err(e) => Err(anyhow::Error::new(e)
        .context("`rustfmt` failed (re-run without .quiet() to see the file it rejected)")),
}
Defensive patterns

Strategy: validation

Validate before calling

// Dry-run rustfmt on a single file to surface the real error before batch formatting:
fn rustfmt_ok(toolchain: &str, file: &Path) -> bool {
    std::process::Command::new("rustfmt")
        .arg(format!("+{toolchain}")).arg("--check").arg(file)
        .output().map(|o| o.status.success()).unwrap_or(false)
}

Type guard

null

Try / catch

// Preserve the underlying error so the user sees which file failed:
match util.format_files(files, cfg, flags) {
    Ok(()) => Ok(()),
    Err(e) if e.to_string().contains("rustfmt` failed") => {
        eprintln!("rustfmt rejected a file; re-run manually without .quiet() to see which");
        Err(e)
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling format_files (miri-script fmt, or any path formatting files) where rustfmt rejects a file — syntax error, an unstable feature not enabled by --unstable-features, edition mismatch, or a rustfmt config incompatibility.

Common situations: A file with a syntax error rustfmt can't parse; using a stable rustfmt that lacks a nightly feature referenced by the config; --edition mismatch (script hardcodes --edition=2024); a rustfmt.toml from a newer rustfmt version.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/e804c58616135725. Report an issue: GitHub.