facebook/flow · error

failed to flush not-covered output

Error message

failed to flush not-covered output

What it means

Flush after the 'File is not @flow!' line in check-contents. Same single-line race as the success-message flush: the writeln fits in the pipe buffer, the reader then exits and closes the pipe, and this out.flush() returns EPIPE (or ENOSPC on a full redirect target); the .expect() turns it into a panic instead of the intended NoError exit.

Source

Thrown at rust_port/crates/flow_cli/src/check_contents_command.rs:204

                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)
        }
    }
}

pub(crate) fn command() -> command_spec::Command {
    command_spec::command(spec(), main)
}

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Rely on the exit code / JSON output instead of text probing
  2. Capture to a file first, then grep the file
  3. Add a buffering `| cat` stage so the flush always succeeds
  4. Maintainer: exit quietly (141) on BrokenPipe at the flush instead of expect

Example fix

// before
out.flush().expect("failed to flush not-covered output");

// after
if let Err(e) = out.flush() {
    if e.kind() == std::io::ErrorKind::BrokenPipe {
        std::process::exit(141);
    }
    panic!("failed to flush not-covered 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 not-covered output: {e}");
}

Prevention

When it happens

Trigger: `flow check-contents module.js | grep -q 'not @flow'` — grep exits after the match, flush gets EPIPE; consumer exiting between write and flush; flushing into a full filesystem.

Common situations: Scripts probing for the not-covered message with grep -q; pipelines with short-lived consumers; disk-full CI environments.

Related errors


AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20). Data as JSON: /api/errors/f9a1c76cafd88d61. Report an issue: GitHub.