{"record":{"id":"d2461911c2b1ef35","repo":"denoland/deno","slug":"too-many-temp-dirs-exist","errorCode":null,"errorMessage":"too many temp dirs exist","messagePattern":"too many temp dirs exist","errorType":"exception","errorClass":"FsError","httpStatus":null,"severity":"error","filePath":"ext/fs/ops.rs","lineNumber":1175,"sourceCode":"  for _ in 0..MAX_TRIES {\n    let path = tmp_name(&mut rng, &dir, prefix.as_deref(), suffix.as_deref())?;\n    // PERMISSIONS: this is ok because we verified the directory above\n    let path = CheckedPath::unsafe_new(Cow::Owned(path));\n    match fs.mkdir_sync(&path, false, Some(0o700)) {\n      Ok(_) => {\n        // PERMISSIONS: ensure the absolute path is not leaked\n        let path =\n          strip_dir_prefix(&dir, dir_arg.as_deref(), path.into_owned_path())?;\n        return path_into_string(path.into_os_string());\n      }\n      Err(FsError::Io(ref e)) if e.kind() == io::ErrorKind::AlreadyExists => {\n        continue;\n      }\n      Err(e) => return Err(e).context(\"tmpdir\"),\n    }\n  }\n\n  Err(FsError::Io(io::Error::new(\n    io::ErrorKind::AlreadyExists,\n    \"too many temp dirs exist\",\n  )))\n  .context(\"tmpdir\")\n}\n\n#[op2(stack_trace)]\n#[string]\npub async fn op_fs_make_temp_dir_async(\n  state: Rc<RefCell<OpState>>,\n  #[string] dir_arg: Option<String>,\n  #[string] prefix: Option<String>,\n  #[string] suffix: Option<String>,\n) -> Result<String, FsOpsError> {\n  let (dir, fs) =\n    make_temp_check_async(state, dir_arg.as_deref(), \"Deno.makeTempDir()\")?;\n\n  let mut rng = thread_rng();","sourceCodeStart":1157,"sourceCodeEnd":1193,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fs/ops.rs#L1157-L1193","documentation":"Deno.makeTempDirSync() tries up to MAX_TRIES=10 times to create a directory named dir + prefix + 8-hex-digit random + suffix (tmp_name uses a random u64), retrying only when creation fails with AlreadyExists. If every attempt collides with an existing path, the op gives up with io::ErrorKind::AlreadyExists 'too many temp dirs exist', wrapped with the context 'tmpdir'.","triggerScenarios":"Deno.makeTempDirSync({ dir, prefix, suffix }) where all 10 generated names already exist: a directory deliberately pre-populated with files matching the prefix/suffix pattern, a test stub of the filesystem that always returns AlreadyExists, or a fixed/seeded RNG in tests producing identical names.","commonSituations":"Unit tests mocking Deno filesystem ops to always throw AlreadyExists; an adversarial or sync-agent process squatting matching names; leftover cleanup scripts that pre-create the exact pattern. With a real 64-bit random name space, natural collisions are practically impossible — this almost always means a stubbed FS or deliberate name squatting.","solutions":["Clean stale files matching the prefix/suffix pattern out of the target directory","Pass a distinct prefix or suffix so generated names stop colliding","Point dir at a fresh empty directory, or omit dir to use the OS temp dir","As a last resort, catch AlreadyExists and retry with a varying prefix"],"exampleFix":"// before\nDeno.makeTempDirSync({ dir: './tmp', prefix: 'job-', suffix: '.tmp' });\n\n// after\nDeno.makeTempDirSync({ dir: './tmp', prefix: `job-${Date.now()}-` });","handlingStrategy":"retry","validationCode":"function cleanTempCollisions(dir: string, prefix: string, suffix: string): void {\n  try {\n    for (const e of Deno.readDirSync(dir)) {\n      const mid = e.name.slice(prefix.length, e.name.length - suffix.length);\n      if (e.name.startsWith(prefix) && e.name.endsWith(suffix) && /^[0-9a-f]{8,}$/.test(mid)) {\n        Deno.removeSync(`${dir}/${e.name}`, { recursive: true });\n      }\n    }\n  } catch { /* directory may not exist yet */ }\n}","typeGuard":null,"tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    const dir = Deno.makeTempDirSync({ prefix: `job-${attempt}-` });\n    // use dir ...\n    break;\n  } catch (e) {\n    if (!(e instanceof Error) || !/too many temp dirs exist/.test(e.message)) throw e;\n  }\n}","preventionTips":["Use a per-call unique prefix (timestamp/uuid fragment) so names cannot collide with leftovers","Clean stale temp entries matching your prefix/suffix pattern","In tests, make filesystem stubs return success or NotFound, never a blanket AlreadyExists"],"tags":["filesystem","temp-dir","collision","already-exists","deno"],"backgroundTag":"temp-file-collision","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}