{"record":{"id":"6edc73f8a73e25e8","repo":"facebook/flow","slug":"failed-to-write-spinner-status-6edc73","errorCode":null,"errorMessage":"failed to write spinner status","messagePattern":"failed to write spinner status","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_commands_connect/src/command_connect.rs","lineNumber":50,"sourceCode":"    pub ignore_version: bool,\n    #[allow(dead_code)]\n    pub emoji: bool,\n    pub quiet: bool,\n    pub show_progress: bool,\n    pub flowconfig_name: &'a str,\n    pub rerun_on_mismatch: bool,\n}\n\nfn print_status(env: &Env<'_>, message: &str) {\n    if env.quiet {\n        return;\n    }\n\n    let stderr = std::io::stderr();\n    let mut stderr = stderr.lock();\n    if env.show_progress && stderr.is_terminal() {\n        write!(stderr, \"{}: {}\", message, flow_utils_tty::spinner(false))\n            .expect(\"failed to write spinner status\");\n    } else {\n        writeln!(stderr, \"{}\", message).expect(\"failed to write status\");\n    }\n    stderr.flush().expect(\"failed to flush status\");\n}\n\nfn arg(name: &str, value: Option<&str>, arr: &mut Vec<String>) {\n    if let Some(value) = value {\n        arr.push(name.to_string());\n        arr.push(value.to_string());\n    }\n}\n\nfn flag(name: &str, value: bool, arr: &mut Vec<String>) {\n    if value {\n        arr.push(name.to_string());\n    }\n}","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/facebook/flow/blob/5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9/rust_port/crates/flow_commands_connect/src/command_connect.rs#L32-L68","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nwrite!(stderr, \"{}: {}\", message, flow_utils_tty::spinner(false))\n    .expect(\"failed to write spinner status\");\n// after\nif write!(stderr, \"{}: {}\", message, flow_utils_tty::spinner(false)).is_err() {\n    return; // status output is best-effort\n}","handlingStrategy":"fallback","validationCode":"use std::io::IsTerminal;\nfn status_output_ok(show_progress: bool) -> bool {\n    std::io::stderr().is_terminal() || std::io::stderr().flush().is_ok()\n}","typeGuard":"fn stderr_alive() -> bool {\n    use std::io::Write;\n    let mut e = std::io::stderr();\n    e.write_all(b\"\").and_then(|_| e.flush()).is_ok()\n}","tryCatchPattern":"match std::panic::catch_unwind(|| run_connect_command()) {\n    Ok(v) => v,\n    Err(_) => eprintln!(\"status write failed; rerun with --quiet and stderr to a file\"),\n}","preventionTips":["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."],"tags":["stderr","terminal-io","panic","spinner","progress"],"backgroundTag":"broken-pipe","analyzedSha":"5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9","analyzedAt":"2026-09-08T04:32:53.179Z","contentChangedAt":"2026-09-08T04:32:53.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}