facebook/flow · error
failed to flush spinner status
Error message
failed to flush spinner status
What it means
In the ServerBusy retry path the client prints `"The flow server ... (N retries remaining)"` with a spinner frame and flushes stderr via `expect("failed to flush spinner status")`. The panic fires when flushing stderr errors — the stderr pipe's reader has closed (EPIPE) or fd 2 is invalid. It surfaces specifically after a `TooManyClients`/busy response, i.e., during long retry loops where a piped reader is likely to have exited.
Source
Thrown at rust_port/crates/flow_commands_connect/src/command_connect.rs:221
BusyReason::FailOnInit(..) => {
"is still initializing and the client used --retry-if-init false"
}
};
if !env.quiet {
eprint!(
"The flow server {} ({} {} remaining): {}",
busy_reason_str,
retries.retries_remaining,
if retries.retries_remaining == 1 {
"retry"
} else {
"retries"
},
flow_utils_tty::spinner(false),
);
std::io::stderr()
.flush()
.expect("failed to flush spinner status");
}
consume_retry(retries);
connect_rec(env, client_handshake, retries)
}
Err(CCSError::BuildIdMismatch(MismatchBehavior::ServerExited)) => {
let msg = "The flow server's version didn't match the client's, so it exited.";
if env.autostart {
if !env.quiet {
eprintln!("{}\nGoing to launch a new one.\n", msg);
}
// Don't decrement retries -- the server is definitely not running,
// so the next time round will hit Server_missing above, *but*
// before that will actually start the server -- we need to make
// sure that happens.
connect_rec(env, client_handshake, retries)
} else {
let msg = format!("\n{}", msg);View on GitHub (pinned to f88ac94bcf)
Solutions
- Redirect stderr to a file or keep the pipe reader alive for the whole command.
- Retry when the server is less loaded (or raise the client limit on the server) so the busy-retry loop is short.
- Code fix: make status-output flushes non-fatal (`let _ = ...flush()`).
Example fix
// before
std::io::stderr().flush().expect("failed to flush spinner status");
// after
let _ = std::io::stderr().flush(); // status line; broken stderr pipe must not kill the client Defensive patterns
Strategy: try-catch
Try / catch
eprint!("The flow server {} ...", ...);
let _ = std::io::stderr().flush(); // status output; EPIPE must not kill retry loop Prevention
- Redirect stderr to a file when scripting flow commands that may retry a busy server.
- Reduce server client load or retry later so busy-retry loops stay short.
- Treat all spinner/status writes to stderr as best-effort in wrapper code.
When it happens
Trigger: Piping stderr to a short-lived reader (`2>&1 | head`) that exits while the client is retrying a busy server; a log collector dying mid-retry; fd 2 closed by the launching wrapper.
Common situations: Scripts piping flow output into head/grep; CI log forwarders that terminate early; servers under heavy client load making the retry loop long enough to outlive the reader.
Related errors
- failed to clear spinner line
- failed to flush spinner status
- failed to clear spinner line
- failed to clear spinner line
- failed to write spinner status
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/a099c3bc357af5a9.
Report an issue: GitHub.