facebook/flow · error
failed to write spinner status
Error message
failed to write spinner status
What it means
Raised by print_status in flow_commands_connect when writing the spinner status line (`message: <spinner>`) to stderr fails. It only takes this path when show_progress is on and stderr is a terminal, so write!(stderr, ...) failing means the terminal write itself errored (EPIPE, closed descriptor, I/O error). The function panics via expect because status output is assumed to always be writable.
Source
Thrown at rust_port/crates/flow_commands_connect/src/command_connect.rs:50
pub ignore_version: bool,
#[allow(dead_code)]
pub emoji: bool,
pub quiet: bool,
pub show_progress: bool,
pub flowconfig_name: &'a str,
pub rerun_on_mismatch: bool,
}
fn print_status(env: &Env<'_>, message: &str) {
if env.quiet {
return;
}
let stderr = std::io::stderr();
let mut stderr = stderr.lock();
if env.show_progress && stderr.is_terminal() {
write!(stderr, "{}: {}", message, flow_utils_tty::spinner(false))
.expect("failed to write spinner status");
} else {
writeln!(stderr, "{}", message).expect("failed to write status");
}
stderr.flush().expect("failed to flush status");
}
fn arg(name: &str, value: Option<&str>, arr: &mut Vec<String>) {
if let Some(value) = value {
arr.push(name.to_string());
arr.push(value.to_string());
}
}
fn flag(name: &str, value: bool, arr: &mut Vec<String>) {
if value {
arr.push(name.to_string());
}
}View on GitHub (pinned to 5c86586199)
Solutions
- Run with a healthy stderr: rerun in a live terminal, or redirect stderr to a file (`2>flow.log`).
- Pass --quiet (or disable progress) so print_status takes the plain writeln path or skips output.
- Avoid piping stderr to consumers that exit early; if piping, use `tail -f` on a file instead.
- If the library is yours, replace the expect with best-effort error handling for stderr writes.
Example fix
// before
write!(stderr, "{}: {}", message, flow_utils_tty::spinner(false))
.expect("failed to write spinner status");
// after
if write!(stderr, "{}: {}", message, flow_utils_tty::spinner(false)).is_err() {
return; // status output is best-effort
} Defensive patterns
Strategy: fallback
Validate before calling
use std::io::IsTerminal;
fn status_output_ok(show_progress: bool) -> bool {
std::io::stderr().is_terminal() || std::io::stderr().flush().is_ok()
} Type guard
fn stderr_alive() -> bool {
use std::io::Write;
let mut e = std::io::stderr();
e.write_all(b"").and_then(|_| e.flush()).is_ok()
} Try / catch
match std::panic::catch_unwind(|| run_connect_command()) {
Ok(v) => v,
Err(_) => eprintln!("status write failed; rerun with --quiet and stderr to a file"),
} Prevention
- Keep stderr attached to a live terminal or a writable file.
- Prefer `cmd 2>file.log` over piping stderr to short-lived consumers.
- Use --quiet for background/IDE-invoked runs.
- For long connect loops, verify the SSH/terminal session stays alive.
When it happens
Trigger: connect_rec or handle_missing_server calls print_status while progress output is enabled and stderr is a TTY whose write fails — e.g. the terminal emulator closed, stderr redirected to a pipe whose reader exited, or a device I/O error.
Common situations: Running `flow connect`-style commands in an IDE terminal that gets closed mid-run; stderr piped into a process like `less` or `head` that exits before the command finishes; SSH session dropped with stderr still attached to the dead pty.
Related errors
- failed to clear spinner line
- failed to write spinner status
- failed to write status
- failed to flush status
- failed to flush spinner status
AI-assisted analysis of facebook/flow@5c86586199 (2026-09-08).
Data as JSON: /api/errors/6edc73f8a73e25e8.
Report an issue: GitHub.