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

{path}: {e}

Error message

{path}: {e}

What it means

This is a recoverable io::Error produced by rustfmt's Session::handle_formatted_file (formatting.rs:304). When source_file::write_file fails (reading the original file or emitting formatted output), rustfmt wraps the underlying io::Error with the offending file path as "{path}: {e}" while preserving the original ErrorKind. Unlike the rustc entries below, this is a returned Err, not a panic.

Source

Thrown at src/tools/rustfmt/src/formatting.rs:304

        psess: &ParseSess,
        path: FileName,
        result: String,
        report: &mut FormatReport,
    ) -> Result<(), ErrorKind> {
        if let Some(ref mut out) = self.out {
            match source_file::write_file(
                Some(psess),
                &path,
                &result,
                out,
                &mut *self.emitter,
                self.config.newline_style(),
            ) {
                Ok(ref result) if result.has_diff => report.add_diff(),
                Err(e) => {
                    // Create a new error with path_str to help users see which files failed
                    let err_msg = format!("{path}: {e}");
                    return Err(io::Error::new(e.kind(), err_msg).into());
                }
                _ => {}
            }
        }

        self.source_file.push((path, result));
        Ok(())
    }
}

pub(crate) struct FormattingError {
    pub(crate) line: usize,
    pub(crate) kind: ErrorKind,
    is_comment: bool,
    is_string: bool,
    pub(crate) line_buffer: String,
}

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. Read the path appended in the message to identify the failing file, then verify it exists and is readable (fix permissions / restore the file).
  2. If piping output, stop the downstream reader from closing early, or write to a file / std::io::sink() instead of a pipe.
  3. In library use, match on the returned Result<(), ErrorKind> and branch on ErrorKind (NotFound, PermissionDenied, BrokenPipe, WriteZero) for targeted recovery.
  4. Check available disk space and that the output target is writable.

Example fix

// before
let report = session.format(input)?; // error text is "{path}: {e}"

// after
match session.format(input) {
    Ok(report) => { /* ... */ }
    Err(ErrorKind::Io(e)) => {
        eprintln!("rustfmt failed on {:?}: {} (kind={:?})", path, e, e.kind());
    }
    Err(other) => return Err(other.into()),
}
Defensive patterns

Strategy: try-catch

Validate before calling

use std::path::Path;
fn can_format(path: &Path) -> bool {
    path.exists() && path.metadata().map(|m| !m.permissions().readonly()).unwrap_or(false)
}

Try / catch

match session.format(input) {
    Ok(report) => { /* apply report */ }
    Err(ErrorKind::Io(e)) => {
        // message is "{path}: {e}"; e.kind() tells you NotFound/PermissionDenied/BrokenPipe
        log::warn!("rustfmt skipped {:?}: {e}", path);
    }
    Err(other) => return Err(other.into()),
}

Prevention

When it happens

Trigger: Calling rustfmt as a library via Session::format_* / handle_formatted_file, or running the rustfmt binary, when write_file returns Err: fs::read_to_string fails (file missing, unreadable, permission denied) or the output Write sink fails (broken pipe, disk full, closed sink).

Common situations: Piping rustfmt output to a command that exits early (e.g. `rustfmt foo.rs | head` -> BrokenPipe), formatting a non-existent or read-only path, a full disk, or a custom Write implementor in library use that returns Err.

Related errors


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