rust-lang/rust · error · FormatDiffError
rustfmt failed with {exit_status}
Error message
rustfmt failed with {exit_status} What it means
Returned by rustfmt's format-diff tool when the spawned rustfmt process exits with a non-success status. The exit status is interpolated into the message and wrapped as ErrorKind::Other (FormatDiffError::IoError). format-diff feeds git-diff ranges to rustfmt via --file-lines; a non-zero exit means rustfmt rejected the input or hit an internal error.
Source
Thrown at src/tools/rustfmt/src/format-diff/main.rs:112
let ranges_as_json = json::to_string(ranges).unwrap();
debug!("Files: {:?}", files);
debug!("Ranges: {:?}", ranges);
let rustfmt_var = env::var_os("RUSTFMT");
let rustfmt = match &rustfmt_var {
Some(rustfmt) => rustfmt,
None => OsStr::new("rustfmt"),
};
let exit_status = process::Command::new(rustfmt)
.args(files)
.arg("--file-lines")
.arg(ranges_as_json)
.status()?;
if !exit_status.success() {
return Err(FormatDiffError::IoError(io::Error::new(
io::ErrorKind::Other,
format!("rustfmt failed with {exit_status}"),
)));
}
Ok(())
}
/// Scans a diff from `from`, and returns the set of files found, and the ranges
/// in those files.
fn scan_diff<R>(
from: R,
skip_prefix: u32,
file_filter: &str,
) -> Result<(HashSet<String>, Vec<Range>), FormatDiffError>
where
R: io::Read,
{
let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{skip_prefix}}}(\S*)");View on GitHub (pinned to 7088e4b63a)
Solutions
- Run the exact rustfmt invocation from the error's context manually to see the real diagnostic.
- Ensure the rustfmt version matches what format-diff expects (nightly for --file-lines).
- Fix syntax errors in the files included in the diff ranges.
- Validate the --file-lines JSON structure against the expected schema.
Example fix
# before: rustfmt --file-lines fails opaquely # after: reproduce and read the real error rustfmt --file-lines file_lines.json --edition 2021 src/lib.rs echo $? # inspect rustfmt's own stderr for the cause
Defensive patterns
Strategy: try-catch
Validate before calling
fn file_lines_json_valid(json: &str) -> bool {
serde_json::from_str::<Vec<serde_json::Value>>(json).is_ok()
}
// Before invoking rustfmt --file-lines, assert file_lines_json_valid(&ranges_as_json). Try / catch
let status = Command::new(rustfmt).args(files).arg("--file-lines").arg(json).status()?;
if !status.success() {
// capture rustfmt's own stderr to report the real diagnostic
return Err(format!("rustfmt failed with {status}").into());
}
Ok(()) Prevention
- Reproduce the exact rustfmt invocation manually to read its real stderr.
- Use a rustfmt version that supports --file-lines (typically nightly).
- Validate the file-lines JSON and fix syntax errors in diffed files before formatting.
When it happens
Trigger: Running `rustfmt --file-lines <json>` (typically via git diff integration / format-diff) where rustfmt exits non-zero - syntax error in the ranged file, invalid --file-lines JSON, rustfmt config error, or an internal rustfmt panic. format-diff checks exit_status.success() and raises this error.
Common situations: Unparsable Rust in the diff range; mismatched rustfmt version that does not support --file-lines; nightly-only config option used on stable rustfmt; malformed file-lines JSON; partial edits that confuse the range formatter.
Related errors
- Error: unable to find a config file for the given path: `{}`
- `rustfmt` failed
- diagnostic error detected
- invalid compression profile: {other}
- unknown compression format: {}
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/e3be8e65f98e4716.
Report an issue: GitHub.