{"record":{"id":"f81855419a835301","repo":"facebook/flow","slug":"failed-to-write-status","errorCode":null,"errorMessage":"failed to write status","messagePattern":"failed to write status","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_commands_connect/src/command_connect.rs","lineNumber":52,"sourceCode":"    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}\n\n// Starts up a flow server by literally calling flow start","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/facebook/flow/blob/5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9/rust_port/crates/flow_commands_connect/src/command_connect.rs#L34-L70","documentation":"Raised by print_status when the non-spinner branch, writeln!(stderr, \"{}\", message), fails to write the plain status message to stderr. This branch runs whenever progress/spinner output is disabled or stderr is not a terminal, and the expect panics because the library assumes status messages can always be written. Failure indicates stderr is closed, redirected to a broken pipe, or hitting an I/O error.","triggerScenarios":"connect_rec or handle_missing_server calls print_status with show_progress off (or stderr not a TTY) while stderr's writer is gone: closed fd 2, piped into a terminated consumer, or disk full when stderr points to a file.","commonSituations":"CI jobs where stderr is redirected to a log file on a full disk; running under wrappers that close stderr; piping output to `head`/`grep -q` that exits early; backgrounding the process with stderr attached to a dead terminal.","solutions":["Redirect stderr to a writable target (file or live terminal) and rerun.","Free disk space if stderr is a log file on a full filesystem.","Stop piping stderr into consumers that terminate before the command completes.","Patch the library to tolerate stderr write failures (log-and-continue) if you control the code."],"exampleFix":"// invocation, before\nflow check 2>&1 | head -n 5\n// after\nflow check 2>flow-check.log; head -n 5 flow-check.log","handlingStrategy":"try-catch","validationCode":"use std::io::Write;\nfn stderr_writable() -> bool {\n    let mut e = std::io::stderr();\n    e.write_all(b\"\").and_then(|_| e.flush()).is_ok()\n}\n// call before invoking; skip/redirect if false","typeGuard":"fn stderr_alive() -> bool { stderr_writable() }","tryCatchPattern":"match std::panic::catch_unwind(|| connect_flow()) {\n    Ok(r) => r,\n    Err(_) => { let _ = std::fs::write(\"flow-status-fallback.log\", \"status write failed\"); std::process::exit(1); }\n}","preventionTips":["Redirect stderr to disk with adequate free space in CI.","Never close fd 2 in wrapper scripts around flow commands.","Avoid `| head` style pipelines on stderr.","Guard long-running jobs with logrotate instead of deleting open log files."],"tags":["stderr","terminal-io","panic","status-output"],"backgroundTag":"broken-pipe","analyzedSha":"5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9","analyzedAt":"2026-09-08T04:32:53.179Z","contentChangedAt":"2026-09-08T04:32:53.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}