{"record":{"id":"79bade75a247524e","repo":"can1357/oh-my-pi","slug":"failed-to-create-a-unique-fc-temporary-file","errorCode":null,"errorMessage":"failed to create a unique fc temporary file","messagePattern":"failed to create a unique fc temporary file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/fc.rs","lineNumber":406,"sourceCode":"struct FcTempFile {\n\tpath: PathBuf,\n}\n\nimpl FcTempFile {\n\tfn create() -> Result<Self, brush_core::Error> {\n\t\tlet temp_dir = std::env::temp_dir();\n\t\tlet process_id = std::process::id();\n\n\t\tfor attempt in 0_u32..100 {\n\t\t\tlet path = temp_dir.join(format!(\"brush-fc-{process_id}-{attempt}.sh\"));\n\t\t\tmatch OpenOptions::new().write(true).create_new(true).open(&path) {\n\t\t\t\tOk(_) => return Ok(Self { path }),\n\t\t\t\tErr(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {},\n\t\t\t\tErr(err) => return Err(err.into()),\n\t\t\t}\n\t\t}\n\n\t\tErr(std::io::Error::new(\n\t\t\tstd::io::ErrorKind::AlreadyExists,\n\t\t\t\"failed to create a unique fc temporary file\",\n\t\t)\n\t\t.into())\n\t}\n\n\tfn path(&self) -> &Path {\n\t\t&self.path\n\t}\n}\n\nimpl Drop for FcTempFile {\n\tfn drop(&mut self) {\n\t\tlet _ = fs::remove_file(&self.path);\n\t}\n}\n\nfn shell_quote_path(path: &Path) -> String {","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/fc.rs#L388-L424","documentation":"The fc builtin's temp-file creator loops attempting to create a uniquely named temporary file (e.g. /tmp/fc.XXXX); if every attempt collides with an existing file it gives up and returns io::ErrorKind::AlreadyExists with this message. It signals exhaustion of the naming space, not a single collision.","triggerScenarios":"Many concurrent fc invocations racing for the same temp-name pattern, a stale directory full of fc.* leftovers, or a broken/predictable RNG making the same name every attempt.","commonSituations":"Heavily parallel shell sessions on shared /tmp, containers with tiny tmpfs and leftover files, or hardened /tmp with sticky-bit + quota issues preventing creation.","solutions":["Clean stale fc temp files from the temp directory, then retry","Retry the command — transient collisions with concurrent sessions usually clear","Use a per-user TMPDIR (TMPDIR=$HOME/.tmp fc ...) to isolate the naming space","If persistent, inspect the temp path for permissions or a full filesystem (`df -h`, `ls -ld $TMPDIR`)"],"exampleFix":"// before\nTMPDIR=/shared-tmp fc -l   // collisions with other users' files\n// after\nmkdir -p ~/.tmp && TMPDIR=$HOME/.tmp fc -l","handlingStrategy":"retry","validationCode":"// pre-flight: ensure TMPDIR is writable and not saturatedlet md = std::fs::metadata(tmpdir)?;assert!(md.is_dir());let count = std::fs::read_dir(tmpdir)?.filter(|e| e.as_ref().unwrap().file_name().to_string_lossy().starts_with(\"fc.\")).count();if count > 10_000 { clean_stale_fc_temps(tmpdir); }","typeGuard":null,"tryCatchPattern":"match FcTemp::create() { Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => { clean_stale_temps(); retry_with_backoff(3); }, Err(e) => return Err(e), Ok(t) => t }","preventionTips":["Give long-lived shells their own TMPDIR to shrink collision space","Periodically clean stale fc.* temp files from shared temp dirs","Keep the temp-creator's random name space large (don't shrink the suffix)"],"tags":["tempfile","io","filesystem","rust"],"backgroundTag":"temp-file-collision","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}