facebook/flow · error
failed to flush cli errors
Error message
failed to flush cli errors
What it means
After printing the collected error/warning report to a locked stdout handle, the flow status-style command flushes the buffer with `out.flush().expect("failed to flush cli errors")`. The panic fires when the flush itself returns an IO error, which in practice means the process on the other end of stdout has gone away (EPIPE/BrokenPipe) or stdout was closed. Rust ignores SIGPIPE by default, so instead of dying silently the write error surfaces here as a panic.
Source
Thrown at rust_port/crates/flow_cli/src/status_command.rs:201
out.flush().expect("failed to flush vim/emacs errors");
} else {
let mut cli_errors = errors.clone();
for (error, _) in &suppressed_errors {
cli_errors.add(error.clone());
}
let stdout = std::io::stdout();
let mut out = stdout.lock();
flow_common_errors::error_utils::cli_output::print_errors(
&mut out,
error_flags,
&None,
strip_root.as_deref(),
&cli_errors,
&warnings,
lazy_msg.as_deref(),
)
.expect("failed to write cli errors");
out.flush().expect("failed to flush cli errors");
}
flow_common_exit_status::exit(command_utils::get_check_or_status_exit_code(
&errors,
&warnings,
error_flags.max_warnings,
))
}
server_prot::response::StatusResponse::NO_ERRORS => {
if args.output_json {
print_json(
&ConcreteLocPrintableErrorSet::empty(),
&ConcreteLocPrintableErrorSet::empty(),
&[],
)
} else {
println!("No errors!");
if let Some(msg) = &lazy_msg {
println!("\n{}", msg);View on GitHub (pinned to f88ac94bcf)
Solutions
- Avoid killing the reader early: write to a file or terminal (`flow status > report.txt`) instead of piping into head/grep -m.
- If scripting, consume the full output or redirect to a file so the pipe never breaks mid-flush.
- If you own the code, treat BrokenPipe as a clean exit: match on `out.flush()` and exit 0 on ErrorKind::BrokenPipe instead of expect.
- In wrapper processes, restore default SIGPIPE behavior (`libc::signal(SIGPIPE, SIG_DFL)`) so the process exits quietly rather than panicking.
Example fix
// before
out.flush().expect("failed to flush cli errors");
// after
if let Err(e) = out.flush() {
if e.kind() != std::io::ErrorKind::BrokenPipe {
panic!("failed to flush cli errors: {e}");
}
std::process::exit(0); // reader went away; report was effectively delivered
} Defensive patterns
Strategy: try-catch
Try / catch
let flush_result = out.flush();
if let Err(e) = flush_result {
if e.kind() == std::io::ErrorKind::BrokenPipe {
std::process::exit(0); // reader went away; treat as success
}
panic!("failed to flush cli errors: {e}");
} Prevention
- Do not pipe flow CLI output into readers that exit early (head, grep -m, quitting pagers); write to files in scripts.
- In wrapper processes, restore default SIGPIPE (`libc::signal(libc::SIGPIPE, libc::SIG_DFL)`) so pipe closure ends the process quietly instead of panicking.
- Keep stdout/stderr readers alive for the full duration of the command.
When it happens
Trigger: Running the command with stdout piped to a short-lived reader that exits before all error output is written: `flow status | head`, `flow check | grep -m1 pattern`, a pager the user quits early, or a log collector that closes the pipe. Also triggered by deliberately closing fd 1 (`>&-`).
Common situations: Shell scripts and CI pipelines that pipe flow CLI output into head/less/grep; wrapper processes that close stdout before the command finishes; large error dumps that outlive a `head -n 10` reader.
Related errors
- failed to write cli errors
- failed to flush cli errors
- failed to flush stdout
- failed to write json errors
- failed to flush json errors
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/00f22ef9e4a25cee.
Report an issue: GitHub.