facebook/flow · error

failed to flush vim/emacs errors

Error message

failed to flush vim/emacs errors

What it means

Flush of the vim/emacs quickfix output from `flow status --from vim|emacs`. The quickfix lines are written to a locked stdout handle; if the report fits the stdio buffer the write succeeds in memory and this flush is where the vanished editor-side reader (BrokenPipe) or a full disk (ENOSPC) is detected, panicking via expect.

Source

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

        } => {
            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");
                out.flush().expect("failed to flush cli errors");

View on GitHub (pinned to 5c86586199)

Solutions

  1. Plugins should wait for the flow process to exit before closing pipes.
  2. Cancel requests by terminating the process rather than closing its stdout.
  3. Redirect output to a file when debugging the integration.
  4. Maintainer fix: BrokenPipe at flush → exit(0) as clean cancellation.

Example fix

// before
out.flush().expect("failed to flush vim/emacs errors");

// after
if let Err(e) = out.flush() {
    if e.kind() != std::io::ErrorKind::BrokenPipe {
        panic!("failed to flush vim/emacs errors: {}", e);
    }
    std::process::exit(0);
}
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = out.flush() {
    if e.kind() != std::io::ErrorKind::BrokenPipe {
        panic!("failed to flush vim/emacs errors: {}", e);
    }
    std::process::exit(0);
}

Prevention

When it happens

Trigger: The editor (or its plugin job) closes the pipe right after buffered writes complete — e.g. quitting vim while a status request is in flight — so flush returns EPIPE; redirected output hitting a full filesystem.

Common situations: Editor integrations cancelling in-flight status requests; scripted runs that close stdout early; disk-full CI environments.

Related errors


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