facebook/flow · error
failed to flush success output
Error message
failed to flush success output
What it means
Flush right after the 'No errors!' line in check-contents. Because a single short line fits in the kernel pipe buffer, the writeln usually succeeds even if the reader is finishing; the reader then fully exits (e.g. grep -q matched the line), the pipe's read end closes, and this explicit out.flush() gets EPIPE — the canonical race that the .expect() turns into a panic.
Source
Thrown at rust_port/crates/flow_cli/src/check_contents_command.rs:189
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 json {
print_json(
&ConcreteLocPrintableErrorSet::empty(),
&ConcreteLocPrintableErrorSet::empty(),
&[],
)
} else {
let stdout = std::io::stdout();
let mut out = stdout.lock();
writeln!(out, "No errors!").expect("failed to write success output");
out.flush().expect("failed to flush success output");
}
flow_common_exit_status::exit(flow_common_exit_status::FlowExitStatus::NoError)
}
server_prot::response::StatusResponse::NOT_COVERED => {
if json {
print_json(
&ConcreteLocPrintableErrorSet::empty(),
&ConcreteLocPrintableErrorSet::empty(),
&[],
)
} else {
let stdout = std::io::stdout();
let mut out = stdout.lock();
writeln!(out, "File is not @flow!").expect("failed to write not-covered output");
out.flush().expect("failed to flush not-covered output");
}
flow_common_exit_status::exit(flow_common_exit_status::FlowExitStatus::NoError)
}View on GitHub (pinned to f88ac94bcf)
Solutions
- Use the exit code instead of probing output: `flow check-contents file.js && echo ok`
- Capture to a file and grep the file rather than the stream
- Wrap the pipeline in a buffer (`| cat`) so the flush always finds a live reader
- Maintainer: exit quietly (141) on BrokenPipe at the flush instead of expect
Example fix
// before
out.flush().expect("failed to flush success output");
// after
if let Err(e) = out.flush() {
if e.kind() == std::io::ErrorKind::BrokenPipe {
std::process::exit(141);
}
panic!("failed to flush success output: {e}");
} Defensive patterns
Strategy: try-catch
Try / catch
if let Err(e) = out.flush() {
if e.kind() == std::io::ErrorKind::BrokenPipe {
std::process::exit(141);
}
panic!("failed to flush success output: {e}");
} Prevention
- Prefer `flow check-contents file.js && echo ok` over `| grep -q 'No errors'`
- When probing output is unavoidable, capture to a file first
- Remember a one-line write can succeed while its flush still fails — test the flush path
When it happens
Trigger: `flow check-contents file.js | grep -q 'No errors'` — grep matches the line, exits, and the subsequent flush hits EPIPE; a probe command exiting between the write and the flush; flush to a full filesystem.
Common situations: CI pipelines that assert on success output via grep -q; short-output commands piped into probes; redirects to full volumes.
Related errors
- failed to flush json errors
- failed to flush cli errors
- failed to flush not-covered output
- failed to write json errors
- failed to write cli errors
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/e8a39cc16d0575de.
Report an issue: GitHub.