{"record":{"id":"5daf57df5dda5e12","repo":"facebook/flow","slug":"pidlog-log-failed-to-write","errorCode":null,"errorMessage":"PidLog::log: failed to write","messagePattern":"PidLog::log: failed to write","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_daemon/src/pid_log.rs","lineNumber":61,"sourceCode":"            .write(true)\n            .open(pids_file)?;\n        *guard = Some(oc);\n        Ok(())\n    })\n}\n\npub fn log(reason: Option<&str>, no_fail: bool, pid: u32) {\n    if !*enabled().lock().expect(\"pid_log enabled mutex poisoned\") {\n        return;\n    }\n    let pid = sys_utils::pid_of_handle(pid);\n    let reason = reason.unwrap_or(\"unknown\");\n    let mut guard = log_oc().lock().expect(\"pid_log log_oc mutex poisoned\");\n    match guard.as_mut() {\n        None if no_fail => {}\n        None => panic!(\"Can't write pid to uninitialized pids log\"),\n        Some(oc) => {\n            writeln!(oc, \"{}\\t{}\", pid, reason).expect(\"PidLog::log: failed to write\");\n            oc.flush().expect(\"PidLog::log: failed to flush\");\n        }\n    }\n}\n\n#[derive(Debug)]\npub struct FailedToGetPids;\n\nimpl std::fmt::Display for FailedToGetPids {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"FailedToGetPids\")\n    }\n}\n\nimpl std::error::Error for FailedToGetPids {}\n\npub fn get_pids(pids_file: &Path) -> Result<Vec<(u32, String)>, FailedToGetPids> {\n    let ic = File::open(pids_file).map_err(|_| FailedToGetPids)?;","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_daemon/src/pid_log.rs#L43-L79","documentation":"Panics when writeln! to the already-opened pids log fails. The pid log records every flow process PID and reason so orphaned daemons can be detected and killed later; the writer is a lazily-initialized global behind a mutex (pid_log::init opens the file). Note that no_fail=true only suppresses the 'uninitialized writer' panic, not a failed write.","triggerScenarios":"Calling pid_log::log after the disk holding the pids file is full; the log file was truncated/moved out from under the open handle (log rotation); the filesystem with the pids file was unmounted (NFS/sshfs home) while the process ran.","commonSituations":"Long-lived flow daemons on CI boxes with full disks; pids.log on a network mount that dropped; external log rotation tools moving the file.","solutions":["Free space on the volume holding the pids file and let the process log again","Point the pids file at a stable local path (pid_log::init argument) not subject to rotation or unmounting","If the write error is from a moved/truncated file, restart the process so init reopens a fresh handle"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm the pids-log target still accepts writes before relying on it\nlet probe = pids_file.with_extension(\"probe\");\nif std::fs::write(&probe, b\"x\").is_err() {\n    // volume full/unwritable: skip enabling the pid log rather than crash later\n    pid_log::disable();\n}\nstd::fs::remove_file(&probe).ok();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the pids file on local, non-rotated storage","Remember no_fail=true only bypasses the uninitialized case; it does not guard write errors","Free disk space on the volume holding the pids log before restarting long-lived processes"],"tags":["rust","logging","io","disk-full"],"backgroundTag":"log-write-failed","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}