facebook/flow · error

failed to clear spinner line

Error message

failed to clear spinner line

What it means

While retrying a connection to the flow server, the client clears the spinner line by writing to stderr via `print_clear_line(...).expect("failed to clear spinner line")`. The panic fires when that stderr write fails — the reader of the stderr pipe has exited (EPIPE) or fd 2 is closed. Clearing the spinner is cosmetic, so the panic kills an otherwise healthy connect attempt over throwaway output.

Source

Thrown at rust_port/crates/flow_commands_connect/src/command_connect.rs:207

        flow_common_exit_status::exit(flow_common_exit_status::FlowExitStatus::OutOfRetries);
    }

    let has_timed_out = match env.expiry {
        None => false,
        Some(t) => Instant::now() >= t,
    };
    if has_timed_out {
        eprintln!("\nTimeout exceeded, exiting");
        flow_common_exit_status::exit(flow_common_exit_status::FlowExitStatus::OutOfTime);
    }

    retries.last_connect_time = Instant::now();

    let conn = CCS::connect_once(env.flowconfig_name, client_handshake, env.tmp_dir, env.root);
    if flow_utils_tty::spinner_used() {
        let stderr = std::io::stderr();
        let mut stderr = stderr.lock();
        flow_utils_tty::print_clear_line(&mut stderr).expect("failed to clear spinner line");
    }

    reset_retries_if_necessary(retries, &conn);

    match conn {
        Ok(conn) => conn,

        Err(CCSError::ServerMissing) => handle_missing_server(env, client_handshake, retries),

        Err(CCSError::ServerBusy(busy_reason)) => {
            let busy_reason_str = match &busy_reason {
                BusyReason::TooManyClients => "has too many clients and rejected our connection",
                BusyReason::NotResponding => "is not responding",
                BusyReason::FailOnInit(..) => {
                    "is still initializing and the client used --retry-if-init false"
                }
            };
            print_status(

View on GitHub (pinned to 5c86586199)

Solutions

  1. Keep the stderr reader alive for the whole command, or redirect stderr to a file (`2>err.log`).
  2. If your wrapper closes fd 2, redirect it to /dev/null instead of closing it.
  3. Code fix: ignore errors from spinner-clearing output since it is cosmetic (`let _ = print_clear_line(...)`).

Example fix

// before
flow_utils_tty::print_clear_line(&mut stderr).expect("failed to clear spinner line");

// after
let _ = flow_utils_tty::print_clear_line(&mut stderr); // cosmetic spinner cleanup; EPIPE is fine
Defensive patterns

Strategy: try-catch

Try / catch

// Spinner output is cosmetic: never fatal
let _ = flow_utils_tty::print_clear_line(&mut stderr);

Prevention

When it happens

Trigger: `flow <cmd> 2>&1 | head` where head exits during connect retries; stderr piped into a process that dies (`2> >(tee log)` with tee killed); running with fd 2 closed (`2>&-`).

Common situations: CLI output piped in scripts; log-shipping sidecars that close their stdin; non-interactive wrappers that close stderr descriptors.

Related errors


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