{"record":{"id":"444013e032f7404b","repo":"Schniz/fnm","slug":"can-t-generate-a-temp-directory","errorCode":null,"errorMessage":"Can't generate a temp directory","messagePattern":"Can't generate a temp directory","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/directory_portal.rs","lineNumber":20,"sourceCode":"use std::path::Path;\nuse tempfile::TempDir;\n\n/// A \"work-in-progress\" directory, which will \"teleport\" into the path\n/// given in `target` only on successful, guarding from invalid state in the file system.\n///\n/// Underneath, it uses `fs::rename`, so make sure to make the `temp_dir` inside the same\n/// mount as `target`. This is why we have the `new_in` constructor.\npub struct DirectoryPortal<P: AsRef<Path>> {\n    temp_dir: TempDir,\n    target: P,\n}\n\nimpl<P: AsRef<Path>> DirectoryPortal<P> {\n    /// Create a new portal which will keep the temp files in\n    /// a subdirectory of `parent_dir` until teleporting to `target`.\n    #[must_use]\n    pub fn new_in(parent_dir: impl AsRef<Path>, target: P) -> Self {\n        let temp_dir = TempDir::new_in(parent_dir).expect(\"Can't generate a temp directory\");\n        debug!(\"Created a temp directory in {}\", temp_dir.path().display());\n        Self { temp_dir, target }\n    }\n\n    pub fn teleport(self) -> std::io::Result<P> {\n        debug!(\n            \"Moving directory {} into {}\",\n            self.temp_dir.path().display(),\n            self.target.as_ref().display()\n        );\n        std::fs::rename(&self.temp_dir, &self.target)?;\n        Ok(self.target)\n    }\n}\n\nimpl<P: AsRef<Path>> std::ops::Deref for DirectoryPortal<P> {\n    type Target = Path;\n    fn deref(&self) -> &Self::Target {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/Schniz/fnm/blob/86adc9676ceb2a509b21e75e74048b93c89f097d/src/directory_portal.rs#L2-L38","documentation":"`DirectoryPortal` stages a download into a `TempDir` created inside `parent_dir` and later atomically `fs::rename`s it onto the target. `new_in` calls `TempDir::new_in(parent_dir).expect(\"Can't generate a temp directory\")`, which panics if the staging directory cannot be created — parent missing, not a directory, permission denied, or no space left on device.","triggerScenarios":"Any install flow using the portal (`fnm install <version>`) when the parent dir — derived from FNM_DIR / the OS data dir — does not exist, is not writable, sits on a read-only or full volume, or a regular file occupies the path where the staging dir should be created.","commonSituations":"FNM_DIR pointing to a nonexistent or permission-locked path; AppData/local-share restrictions on managed machines; disk full mid-download-day; leftovers from a previous crashed install blocking the staging location; network mounts with odd create semantics.","solutions":["Verify the parent: `mkdir -p \"$FNM_DIR\" && touch \"$FNM_DIR/.probe\" && rm \"$FNM_DIR/.probe\"` — any failure pinpoints the permission/space issue.","Free space on the volume holding FNM_DIR (or move FNM_DIR to a larger disk).","Remove stale partial staging entries under the fnm dir from earlier failed installs, then retry.","If patching fnm: propagate the io::Error (`TempDir::new_in(dir).map_err(...)?`) instead of expect."],"exampleFix":"// before (src/directory_portal.rs)\nlet temp_dir = TempDir::new_in(parent_dir).expect(\"Can't generate a temp directory\");\n\n// after\nlet temp_dir = TempDir::new_in(parent_dir)\n    .map_err(|e| anyhow::anyhow!(\"Can't generate a temp directory in {}: {e}\", parent_dir.as_ref().display()))?;","handlingStrategy":"validation","validationCode":"fn staging_dir_ready(base: &Path) -> std::io::Result<()> {\n    std::fs::create_dir_all(base)?;\n    let probe = tempfile::Builder::new().prefix(\"probe\").tempdir_in(base)?;\n    drop(probe); // create+remove succeeded => writable and has space\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"std::panic::catch_unwind(|| directory_portal_new_in(parent, target))\n    .unwrap_or_else(|_| {\n        eprintln!(\"staging dir under {} unusable: check existence, permissions, disk space\", parent.display());\n    });","preventionTips":["Pre-create FNM_DIR during setup and verify write access with a probe file.","Keep the FNM_DIR volume below ~90% usage before large installs.","Clean partial staging leftovers after failed installs before retrying."],"tags":["rust","temp-dir","install","filesystem","permissions","panic"],"backgroundTag":"temp-dir-creation-failed","analyzedSha":"86adc9676ceb2a509b21e75e74048b93c89f097d","analyzedAt":"2026-08-16T21:43:05.725Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}