facebook/flow · error

failed to write json errors

Error message

failed to write json errors

What it means

For `flow status --output-json`, the CLI writes the machine-readable error report to a locked stdout via flow_common_errors::error_utils::json_output::print_errors_with_offset_kind; this expect panics on the first write error. Rust ignores SIGPIPE, so a downstream JSON consumer that exits early (head, a crashing jq pipeline stage) surfaces here as ErrorKind::BrokenPipe.

Source

Thrown at rust_port/crates/flow_cli/src/status_command.rs:149

         suppressed_errors: &[(PrintableError<Loc>, BTreeSet<Loc>)]| {
            let strip_root = strip_root
                .as_deref()
                .map(|root| root.to_string_lossy().into_owned());
            let stdout = std::io::stdout();
            let mut out = stdout.lock();
            flow_common_errors::error_utils::json_output::print_errors_with_offset_kind(
                &mut out,
                strip_root.as_deref(),
                suppressed_errors,
                args.pretty,
                args.output_json_version
                    .unwrap_or(json_output::JsonVersion::JsonV1),
                &None,
                offset_kind,
                errors,
                warnings,
            )
            .expect("failed to write json errors");
            out.flush().expect("failed to flush json errors");
        };
    let lazy_msg = if lazy_stats.lazy_mode {
        Some(format!(
            "The Flow server is currently in lazy mode and is only checking {}/{} files.\nTo learn more, visit flow.org/en/docs/lang/lazy-modes",
            lazy_stats.checked_files, lazy_stats.total_files
        ))
    } else {
        None
    };
    match response {
        server_prot::response::StatusResponse::ERRORS {
            errors,
            warnings,
            suppressed_errors,
        } => {
            let error_flags = &args.error_flags;
            let from = flow_event_logger::get_from_i_am_a_clown();

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Capture to a file first: `flow status --output-json > status.json`, then parse the file.
  2. Make the consumer read the entire stream (replace head/grep -m with full parsers).
  3. Free disk space for redirected output.
  4. Maintainer fix: BrokenPipe → silent exit(0); other io errors → report.

Example fix

// before
flow_common_errors::error_utils::json_output::print_errors_with_offset_kind(/* ... */)
    .expect("failed to write json errors");

// after
if let Err(e) = flow_common_errors::error_utils::json_output::print_errors_with_offset_kind(/* ... */) {
    if e.kind() == std::io::ErrorKind::BrokenPipe {
        std::process::exit(0);
    }
    panic!("failed to write json errors: {}", e);
}
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = flow_common_errors::error_utils::json_output::print_errors_with_offset_kind(/* args */) {
    if e.kind() == std::io::ErrorKind::BrokenPipe {
        std::process::exit(0);
    }
    panic!("failed to write json errors: {}", e);
}

Prevention

When it happens

Trigger: `flow status --output-json | jq '.errors' | head -3` where head quits early; a consumer parsing the JSON that exits on the first result; stdout redirected to a full disk; running with stdout closed.

Common situations: Editor/IDE plugins and CI scripts that consume only a prefix of the JSON status; full CI artifact disks; pipelines with early-terminating stages.

Related errors


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