facebook/flow · error
failed to write errors
Error message
failed to write errors
What it means
After a foreground (check-and-die) run with JSON output (e.g. `flow check-contents --json --pretty`), the CLI formats the error report and writes it to a BufWriter over stdout. This expect is on the pretty-printed branch (flow_hh_json::json_to_multiline) and panics on any write error. Because Rust ignores SIGPIPE, a downstream consumer that exited early surfaces here as ErrorKind::BrokenPipe instead of a signal.
Source
Thrown at rust_port/crates/flow_cli/src/foreground_check_commands.rs:84
let strip_root = strip_root.map(|path| path.to_string_lossy().into_owned());
let pretty = *pretty;
let get_json = json_output::full_status_json_of_errors(
strip_root.as_deref(),
suppressed_errors,
version.clone().unwrap_or(json_output::JsonVersion::JsonV1),
&None,
offset_kind,
errors,
warnings,
);
let finish_formatting = move |profiling_props| {
let res = get_json(profiling_props);
let stdout = std::io::stdout();
let mut out = std::io::BufWriter::new(stdout.lock());
use std::io::Write;
if pretty {
write!(out, "{}", flow_hh_json::json_to_multiline(&res))
.expect("failed to write errors");
} else {
write!(out, "{}", flow_hh_json::json_string_of_value(&res))
.expect("failed to write errors");
}
out.flush().expect("failed to flush errors");
};
Box::new(move |profiling| {
let profiling_props = match profiling {
Some(serde_json::Value::Object(profiling_props)) => {
profiling_props.into_iter().collect()
}
Some(_) | None => vec![],
};
finish_formatting(profiling_props);
})
}
Printer::Cli(flags) => {
let errors = suppressed_errorsView on GitHub (pinned to 5c86586199)
Solutions
- Write to a file first and inspect it separately: `flow check-contents --json --pretty > report.json`.
- Keep the pipe consumer alive until EOF (drop `head`/`grep -m` from the pipeline).
- If redirecting to a file, free disk space / raise quota.
- Maintainer fix: treat ErrorKind::BrokenPipe as a clean exit(0), the standard CLI convention.
Example fix
// before
write!(out, "{}", flow_hh_json::json_to_multiline(&res))
.expect("failed to write errors");
// after
if let Err(e) = write!(out, "{}", flow_hh_json::json_to_multiline(&res)) {
if e.kind() == std::io::ErrorKind::BrokenPipe {
std::process::exit(0);
}
panic!("failed to write errors: {}", e);
} Defensive patterns
Strategy: try-catch
Try / catch
if let Err(e) = write!(out, "{}", flow_hh_json::json_to_multiline(&res)) {
if e.kind() == std::io::ErrorKind::BrokenPipe {
std::process::exit(0);
}
panic!("failed to write errors: {}", e);
} Prevention
- Redirect large JSON reports to files instead of piping to head/grep -m.
- Keep downstream consumers reading until EOF.
- Ensure redirected targets have free disk space; never run with stdout closed.
When it happens
Trigger: `flow check-contents --json --pretty | head -n 5` (head exits after 5 lines, closing the pipe); a downstream filter that exits early (grep -m1, jq ... | head); stdout redirected to a full filesystem (ENOSPC); stdout closed with `>&-`.
Common situations: Piping large JSON check output into head/grep in scripts; CI capturing output to a full disk or size-capped artifact; a consumer tool crashing mid-stream.
Related errors
- failed to write json errors
- failed to flush json errors
- failed to write json errors
- failed to flush errors
- failed to write cli errors
AI-assisted analysis of facebook/flow@5c86586199 (2026-08-20).
Data as JSON: /api/errors/670d6776a7ce99a9.
Report an issue: GitHub.