{"record":{"id":"f82d3250b1d49408","repo":"herdrdev/herdr","slug":"failed-to-create-unique-scrollback-temp-file","errorCode":null,"errorMessage":"failed to create unique scrollback temp file","messagePattern":"failed to create unique scrollback temp file","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"src/app/input/navigate.rs","lineNumber":2016,"sourceCode":"        {\n            use std::os::unix::fs::OpenOptionsExt;\n            options.mode(0o600);\n        }\n\n        match options.open(&path) {\n            Ok(mut file) => {\n                file.write_all(content.as_bytes())?;\n                return Ok(path);\n            }\n            Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {\n                last_collision = Some(err);\n            }\n            Err(err) => return Err(err),\n        }\n    }\n\n    Err(last_collision.unwrap_or_else(|| {\n        io::Error::new(\n            io::ErrorKind::AlreadyExists,\n            \"failed to create unique scrollback temp file\",\n        )\n    }))\n}\n\nfn unique_scrollback_path(attempt: u32) -> std::path::PathBuf {\n    let nanos = SystemTime::now()\n        .duration_since(UNIX_EPOCH)\n        .map(|duration| duration.as_nanos())\n        .unwrap_or(0);\n    std::env::temp_dir().join(format!(\n        \"herdr-scrollback-{}-{nanos}-{attempt}.txt\",\n        std::process::id()\n    ))\n}\n\n#[cfg(test)]","sourceCodeStart":1998,"sourceCodeEnd":2034,"githubUrl":"https://github.com/herdrdev/herdr/blob/f457cff4f2648eee85d176f8a41861241d4e8428/src/app/input/navigate.rs#L1998-L2034","documentation":"open_focused_scrollback_in_editor needs a temp file for the pane's scrollback, so write_scrollback_temp_file retries with unique candidate names. If every attempt fails — either each name collided (AlreadyExists) or another I/O error occurred — it returns ErrorKind::AlreadyExists with 'failed to create unique scrollback temp file' (the fallback when even the collision loop produced no actionable error). In practice the temp directory is unwritable, full, or the name-generation space is exhausted.","triggerScenarios":"Calling open_focused_scrollback_in_editor when the temp dir (e.g. /tmp or TMPDIR) is not writable, full (ENOSPC), or has thousands of same-prefix files making unique-name retries collide; also when the temp dir does not exist.","commonSituations":"TMPDIR pointing to a read-only or missing directory in containers/sandboxes; disk-full CI runners; sandboxed apps denied temp writes; leftover herdr scrollback temp files accumulating from crashes.","solutions":["Check TMPDIR (or /tmp) is writable and has free space: touch $TMPDIR/probe && df -h $TMPDIR.","Set TMPDIR to a writable location with space before launching herdr.","Clean up stale herdr scrollback temp files that may be causing collisions.","If it persists, capture the underlying last_collision error in tracing to see the real OS error (permissions vs ENOSPC vs name collisions)."],"exampleFix":"# before\nTMPDIR=/readonly/tmp herdr\n\n# after\nmkdir -p ~/.cache/herdr-tmp\nTMPDIR=~/.cache/herdr-tmp herdr","handlingStrategy":"fallback","validationCode":"let tmp = std::env::temp_dir();\nlet probe = tmp.join(\".herdr_probe\");\nstd::fs::write(&probe, b\"\")?; // fails fast with the real OS error if TMPDIR is unusable\nstd::fs::remove_file(&probe)?;","typeGuard":null,"tryCatchPattern":"match write_scrollback_temp_file(&scrollback) {\n    Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {\n        // temp dir unusable or saturated: fall back to in-app viewer, surface actionable message to user\n    }\n    other => other,\n}","preventionTips":["Launch herdr with a writable, spacious TMPDIR in containers and CI.","Periodically clean stale herdr temp files after crashes.","Fail fast on temp-dir writability at startup rather than at first use."],"tags":["filesystem","temp-file","scrollback","env","rust"],"backgroundTag":"temp-file-creation-failed","analyzedSha":"f457cff4f2648eee85d176f8a41861241d4e8428","analyzedAt":"2026-08-28T15:41:09.197Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}