facebook/flow · error

failed to write success output

Error message

failed to write success output

What it means

Happy path of check-contents: the server answers StatusResponse::NO_ERRORS and, without --json, the CLI writes the single line 'No errors!' to locked stdout. Even one writeln can fail: once the pipe's read end is fully closed (consumer exited or fd closed), any write returns EPIPE immediately, so the .expect() panics before the NoError exit status is set.

Source

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

                // Return a successful exit code if there were only warnings.
                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

  1. Capture to a file and test the file: `flow check-contents file.js > out.txt; test $? -eq 0`
  2. Make the downstream consumer read until EOF instead of exiting early
  3. Ensure the CLI's stdout is a live pipe or file (never closed) in wrappers
  4. Maintainer: match the writeln result and exit(141) on BrokenPipe instead of expect

Example fix

// before
writeln!(out, "No errors!").expect("failed to write success output");

// after
if let Err(e) = writeln!(out, "No errors!") {
    if e.kind() == std::io::ErrorKind::BrokenPipe {
        std::process::exit(141);
    }
    panic!("failed to write success output: {e}");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Consumers should read until EOF rather than exit early:
// (pattern for a wrapper that inspects output then decides)
// flow check-contents file.js > out.txt   # always drains the writer

Try / catch

if let Err(e) = writeln!(out, "No errors!") {
    if e.kind() == std::io::ErrorKind::BrokenPipe {
        std::process::exit(141);
    }
    panic!("failed to write success output: {e}");
}

Prevention

When it happens

Trigger: `flow check-contents file.js | true` or a fast-failing validation step that exits without reading; a consumer that exits before the CLI's write lands (race); stdout closed via `>&-` or an invalid redirect.

Common situations: Scripts using `cmd | grep -q SomethingElse` patterns where the probe exits; wrappers that spawn the CLI but close the pipe early on their own error paths; sandboxed environments closing stdout fds.

Related errors


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