gleam-lang/gleam · warning

Final result error writing

Error message

Final result error writing

What it means

When the gleam CLI main function finishes with an Err, it pretty-prints the error to stderr and uses .expect("Final result error writing") on the print operation. If writing to stderr fails, this panics. It only triggers while already reporting a failure, so it compounds an existing error.

Solutions

  1. Ensure stderr is writable and the consuming pipe/process is still alive when running gleam commands
  2. Fix the underlying command failure first — this panic only occurs while reporting another error
  3. Avoid closing/redirecting stderr in CI wrappers that run gleam
  4. Report a broken-pipe scenario upstream if it happens in normal terminal use

Example fix

// before
$ gleam build 2>&1 | head -1   # downstream closes the pipe early
// after
$ gleam build 2>&1 | tee build.log   # keep the consumer alive while gleam writes
Defensive patterns

Strategy: try-catch

Validate before calling

fn stderr_is_writable() -> bool {
    use std::io::Write;
    std::io::stderr().flush().is_ok()
}

Try / catch

if let Err(e) = write_stderr(&buffer) {
    eprintln!("could not report error: {}", e);
    std::process::exit(1);
}

Prevention

When it happens

Trigger: The command failed (main returned Err), and stderr.print(&buffer) fails — typically because stderr is closed, redirected to a file/pipe that is full or unwritable, or the terminal detached.

Common situations: Running `gleam build 2>/dev/null` in environments where /dev/null write fails, CI runners with closed stderr descriptors, piping gleam output to a process that exited early (broken pipe), or a full disk when redirecting output to a file.

Related errors


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

Appendix: source

Thrown at compiler-cli/src/lib.rs:968

        version: String,
    },
}

pub fn main() {
    initialise_logger();
    panic::add_handler();
    let stderr = cli::stderr_buffer_writer();
    let result = get_current_directory()
        .and_then(|working_directory| Command::parse().run(working_directory));
    match result {
        Ok(_) => {
            tracing::info!("Successfully completed");
        }
        Err(error) => {
            tracing::error!(error = ?error, "Failed");
            let mut buffer = stderr.buffer();
            error.pretty(&mut buffer);
            stderr.print(&buffer).expect("Final result error writing");
            std::process::exit(1);
        }
    }
}

fn command_check(paths: &ProjectPaths, target: Option<Target>) -> Result<()> {
    let _ = build::main(
        paths,
        Options {
            root_target_support: TargetSupport::Enforced,
            warnings_as_errors: false,
            codegen: Codegen::DepsOnly,
            compile: Compile::All,
            mode: Mode::Dev,
            target,
            no_print_progress: false,
            erlang_output: ErlangOutput::Binary,
        },

View on GitHub (pinned to 49f8762da5)