Schniz/fnm · critical
Can't get a temporary file
Error message
Can't get a temporary file
What it means
When a Node install artifact is a zip (the Windows distribution path), `Zip::extract_into` first streams the download into an unnamed temp file created by `tempfile::tempfile()` in the OS temp dir (TMPDIR/TEMP/TMP, else the system temp). Any io::Error from creating that file hits `.expect("Can't get a temporary file")` and panics, aborting the install mid-flight.
Source
Thrown at src/archive/zip.rs:22
use std::io::{self, Read};
use std::path::Path;
use tempfile::tempfile;
use zip::read::ZipArchive;
pub struct Zip<R: Read> {
response: R,
}
impl<R: Read> Zip<R> {
#[allow(dead_code)]
pub fn new(response: R) -> Self {
Self { response }
}
}
impl<R: Read> Extract for Zip<R> {
fn extract_into(mut self: Box<Self>, path: &Path) -> Result<(), Error> {
let mut tmp_zip_file = tempfile().expect("Can't get a temporary file");
debug!("Created a temporary zip file");
io::copy(&mut self.response, &mut tmp_zip_file)?;
debug!(
"Wrote zipfile successfully. Now extracting into {}.",
path.display()
);
let mut archive = ZipArchive::new(&mut tmp_zip_file)?;
for i in 0..archive.len() {
let mut file = archive.by_index(i)?;
let outpath = path.join(file.mangled_name());
{
let comment = file.comment();
if !comment.is_empty() {
debug!("File {i} comment: {comment}");View on GitHub (pinned to 86adc9676c)
Solutions
- Point temp at a writable dir and retry: Windows `set TEMP=C:\Users\me\AppData\Local\Temp` / Unix `TMPDIR=/var/tmp fnm install 20`.
- Create the configured temp dir if missing: `mkdir -p "$TMPDIR"` (or recreate %TEMP%).
- Free space on the temp volume and raise tmpfs size or relocate it (`tmpfs` in /etc/fstab).
- If patching fnm: replace `.expect(...)` with `.map_err(|e| anyhow::anyhow!("can't create temp file: {e}"))?` so it reports instead of panicking.
Example fix
// before (src/archive/zip.rs)
let mut tmp_zip_file = tempfile().expect("Can't get a temporary file");
// after
let mut tmp_zip_file = tempfile()
.map_err(|e| anyhow::anyhow!("Can't get a temporary file: {e}"))?; Defensive patterns
Strategy: validation
Validate before calling
fn temp_dir_writable() -> bool {
let dir = std::env::temp_dir();
std::fs::create_dir_all(&dir).is_ok()
&& tempfile::tempfile().is_ok()
};
// also check free space: statvfs / GetDiskFreeSpaceEx before large installs Try / catch
std::panic::catch_unwind(|| fnm_install(version)) // or invoke the binary
.unwrap_or_else(|_| {
eprintln!("install failed — check TMPDIR/TEMP writability and disk space");
std::process::exit(1);
}); Prevention
- Pin TMPDIR/TEMP to a known writable directory in CI and containers.
- Ensure the temp volume has headroom larger than the Node zip before installing.
- Monitor disk space on tmpfs mounts; prefer disk-backed /var/tmp for big downloads.
When it happens
Trigger: `fnm install <version>` (zip-based artifact, typically Windows) when the temp dir is missing, unwritable, full, or the process exhausted its file-descriptor quota — e.g. TMPDIR=/nonexistent, a full tmpfs /tmp, or a sandbox (Snap/Flatpak) denying writes to the default temp location.
Common situations: Docker/CI overriding TMPDIR to a path that was never created; small tmpfs /tmp filling during large downloads; TEMP pointing to a deleted per-user temp folder after cleanup tools ran; disk quota exhaustion on multi-tenant runners.
Related errors
- Can't generate a temp directory
- Can't join paths: {source}
- Can't read PATH
- Can't read PATH env var
- Can't join paths: {err}
AI-assisted analysis of Schniz/fnm@86adc9676c (2026-08-16).
Data as JSON: /api/errors/9c934bac67724e23.
Report an issue: GitHub.