gleam-lang/gleam · error

write new line after diagnostic

Error message

write new line after diagnostic

What it means

In `Error::pretty`, each rendered diagnostic is written to the output buffer followed by `writeln!(buffer).expect("write new line after diagnostic")`. `writeln!` returns `Err` if the underlying writer fails; since the buffer is an in-memory `codespan` `Buffer` this should be infallible, so the `expect` asserts the invariant that writing to the buffer never fails. A panic here means the writer implementation or buffer state is broken.

Solutions

  1. Avoid piping the compiler output into commands that close the pipe early, or ignore SIGPIPE (`trap '' PIPE`)/use `std::io::sink`-safe output paths
  2. Upgrade Gleam — CLI output writing has been progressively hardened against broken pipes
  3. If embedding, pass the standard `Buffer::no_color()`/`Buffer::ansi()` which write to memory and cannot fail

Example fix

// before
writeln!(buffer).expect("write new line after diagnostic");
// after
if writeln!(buffer).is_err() {
    return; // downstream writer is gone; stop rendering diagnostics
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check output sink writability before running the compiler, e.g. avoid closed pipes:
// gleam build | head   <-- avoid; use full output redirect instead

Try / catch

match std::process::Command::new("gleam").arg("build").output() {
    Ok(out) => print!("{}", String::from_utf8_lossy(&out.stdout)),
    Err(e) => eprintln!("compiler output failed: {e}"), // includes broken-pipe cases
}

Prevention

When it happens

Trigger: `writeln!(buffer)` returns `Err` — realistically only when `pretty` is (or becomes) callable with a custom `Buffer`-like writer whose `write` implementation errors (disk full, closed pipe such as `gleam build | head`, or a mocked writer in tests that intentionally fails).

Common situations: Piping compiler output to a short-lived reader (e.g. `gleam check | head -1`) where the pipe is closed (broken pipe), or embedding the library with a custom buffer backed by a failing sink.

Related errors


AI-assisted analysis of gleam-lang/gleam@49f8762da5 (2026-09-14). Data as JSON: /api/errors/ac2c4f378bf7f0a3. Report an issue: GitHub.

Appendix: source

Thrown at compiler-core/src/error.rs:1007

        _ if value / 10 == 1 => format!("{value}th"),
        1 => format!("{value}st"),
        2 => format!("{value}nd"),
        3 => format!("{value}rd"),
        _ => format!("{value}th"),
    }
}

impl Error {
    pub fn pretty_string(&self) -> String {
        let mut nocolor = Buffer::no_color();
        self.pretty(&mut nocolor);
        String::from_utf8(nocolor.into_inner()).expect("Error printing produced invalid utf8")
    }

    pub fn pretty(&self, buffer: &mut Buffer) {
        for diagnostic in self.to_diagnostics() {
            diagnostic.write(buffer);
            writeln!(buffer).expect("write new line after diagnostic");
        }
    }

    pub fn skipped_files_diagnostics(&self) -> HashMap<Utf8PathBuf, Diagnostic> {
        let Error::Type {
            skipped_modules, ..
        } = self
        else {
            return HashMap::new();
        };

        skipped_modules
            .iter()
            .map(|skipped_module| {
                let text = match &skipped_module.reason {
                    SkipReason::DependencyHasError { .. } => {
                        "The current module cannot be analysed because this \
imported module has errors."

View on GitHub (pinned to 49f8762da5)