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
- 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).
- Debounce/cancel cleanly: kill the flow process instead of just closing its stdout pipe.
- For manual debugging, redirect to a file: `flow status --from vim > /tmp/errors`.
- 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
- Editor plugins must keep the spawned flow process's stdout open until the process exits (await exit, then close).
- Cancel in-flight requests by terminating the process, not by closing the pipe.
- Redirect to a temp file when debugging editor integrations.
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
- failed to flush vim/emacs errors
- failed to write cli errors
- failed to flush cli errors
- failed to flush stdout
- failed to write json errors
AI-assisted analysis of facebook/flow@5c86586199 (2026-08-20).
Data as JSON: /api/errors/fb1316f17e07f08b.
Report an issue: GitHub.