facebook/flow · error

failed to write vim/emacs errors

Error message

failed to write vim/emacs errors

What it means

With `flow status --from vim` (or emacs), the CLI writes errors in the vim/emacs quickfix format directly to a locked stdout for editor integrations; this expect panics on the first write error. The classic cause is the editor-side pipe disappearing — the user quits the editor, the plugin's job is cancelled, or the process group is killed — while flow is still writing error lines.

Source

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

            suppressed_errors,
        } => {
            let error_flags = &args.error_flags;
            let from = flow_event_logger::get_from_i_am_a_clown();
            if args.output_json {
                print_json(&errors, &warnings, &suppressed_errors)
            } else if matches!(from.as_deref(), Some("vim") | Some("emacs")) {
                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::vim_emacs_output::print_errors(
                    strip_root.as_deref(),
                    &mut out,
                    &errors,
                    &warnings,
                )
                .expect("failed to write vim/emacs errors");
                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");

View on GitHub (pinned to 5c86586199)

Solutions

  1. In the editor plugin, keep the job's pipe open until the flow process exits (await process completion, e.g. Neovim jobwait / job_close after exit).
  2. Debounce/cancel cleanly: kill the flow process instead of just closing its stdout pipe.
  3. For manual debugging, redirect to a file: `flow status --from vim > /tmp/errors`.
  4. Maintainer fix: treat BrokenPipe as a normal cancellation and exit 0 silently.

Example fix

# before (editor plugin shell)
flow status --from vim | head -100   # head exits, flow panics on EPIPE

# after (editor plugin shell)
flow status --from vim > /tmp/flow-errors.$$
# then read the full file
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = flow_common_errors::error_utils::vim_emacs_output::print_errors(strip_root.as_deref(), &mut out, &errors, &warnings) {
    if e.kind() == std::io::ErrorKind::BrokenPipe {
        std::process::exit(0); // editor went away; treat as cancelled
    }
    panic!("failed to write vim/emacs errors: {}", e);
}

Prevention

When it happens

Trigger: A vim/emacs flow plugin spawns `flow status --from vim`, the user closes the buffer/editor or a new keystroke cancels the job, and the pipe reader exits before flow finishes writing the quickfix list.

Common situations: Editor integrations (ALE-style, flow-language-plugin) that spawn status requests and cancel them on new input; users quitting vim mid-check; flaky EPIPE panics littering editor plugin logs.

Related errors


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