denoland/deno · error · FsError
too many temp files exist
Error message
too many temp files exist
What it means
Deno.makeTempFileSync() generates up to 10 candidate names (dir + prefix + 8-hex random + suffix) and creates each with an exclusive create; AlreadyExists means the name is taken and the loop retries. If all 10 attempts collide, it fails with io::ErrorKind::AlreadyExists 'too many temp files exist', wrapped with context 'tmpfile'.
Source
Thrown at ext/fs/ops.rs:1263
for _ in 0..MAX_TRIES {
let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;
// PERMISSIONS: this is fine because the dir was checked
let path = CheckedPath::unsafe_new(Cow::Owned(path));
match fs.open_sync(&path, open_opts) {
Ok(_) => {
// PERMISSIONS: ensure the absolute path is not leaked
let path =
strip_dir_prefix(&dir, dir_arg.as_deref(), path.into_owned_path())?;
return path_into_string(path.into_os_string());
}
Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {
continue;
}
Err(e) => return Err(e).context("tmpfile"),
}
}
Err(FsError::Io(io::Error::new(
io::ErrorKind::AlreadyExists,
"too many temp files exist",
)))
.context("tmpfile")
}
#[op2(stack_trace)]
#[string]
pub async fn op_fs_make_temp_file_async(
state: Rc<RefCell<OpState>>,
#[string] dir_arg: Option<String>,
#[string] prefix: Option<String>,
#[string] suffix: Option<String>,
) -> Result<String, FsOpsError> {
let (dir, fs) =
make_temp_check_async(state, dir_arg.as_deref(), "Deno.makeTempFile()")?;
let open_opts = OpenOptions {View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Remove stale files matching the prefix/suffix pattern from the directory
- Choose a fresh prefix or suffix
- Omit dir to create in the OS temp directory
- Retry with a different prefix when AlreadyExists surfaces
Example fix
// before
const f = Deno.makeTempFileSync({ dir: './tmp', prefix: 'up-', suffix: '.part' });
// after
const f = Deno.makeTempFileSync({ dir: './tmp', prefix: `up-${Date.now()}-` }); Defensive patterns
Strategy: retry
Validate before calling
function makeTempFileSafe(opts: Deno.MakeTempOptions = {}): string {
for (let i = 0; i < 3; i++) {
try {
return Deno.makeTempFileSync({ ...opts, prefix: `${opts.prefix ?? ''}${Date.now()}-` });
} catch (e) {
if (!(e instanceof Error) || !/too many temp files exist/.test(e.message)) throw e;
}
}
throw new Error('temp file creation exhausted retries');
} Try / catch
try {
path = Deno.makeTempFileSync({ dir, prefix, suffix });
} catch (e) {
if (e instanceof Error && /too many temp files exist/.test(e.message)) {
path = Deno.makeTempFileSync({ dir, prefix: `${prefix}${crypto.randomUUID().slice(0, 8)}-`, suffix });
} else {
throw e;
}
} Prevention
- Use unique prefixes so the 10-attempt random space never matters
- Keep the target directory free of files matching your prefix/suffix pattern
- Fix test doubles that blanket-return AlreadyExists
When it happens
Trigger: Deno.makeTempFileSync({ dir, prefix, suffix }) where every generated name matches an existing file — a stubbed filesystem in tests that always answers AlreadyExists, or a directory pre-seeded with the exact prefix/suffix + hex pattern.
Common situations: Test doubles intercepting file creation; file-sync or antivirus agents racing creation; nearly impossible naturally because tmp_name draws from a 64-bit random space — real occurrences almost always involve mocking or name squatting.
Related errors
- too many temp dirs exist
- ERR_FS_EISDIR
- sockets cannot be copied
- the source path is not a valid file
- Path has no root.
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/64320f6e97c3f4be.
Report an issue: GitHub.