jdx/mise · error
path component {} was concurrently created by another user
Error message
path component {} was concurrently created by another user What it means
This error is raised by mise's managed-file bookkeeping when a path component that mise just created was found to already exist (or have different identity) by the time it was opened. If mise's own record shows it created that component, the file was swapped out from under it (replaced) before opening; if not, another user/process created it concurrently. It is a deliberate TOCTOU safety guard against symlink/race attacks on shared directories.
Source
Thrown at src/system/managed_files.rs:1672
});
}
};
let created = openat(&directory, name.as_os_str(), flags, Mode::empty())
.wrap_err_with(|| {
format!(
"failed to open newly available path component {} without following symlinks",
component_path.display()
)
})?;
let stat = nix::sys::stat::fstat(&created)?;
if stat.st_uid != nix::unistd::geteuid().as_raw() {
if created_by_us {
bail!(
"created path component {} was replaced before it could be opened",
component_path.display()
);
} else {
bail!(
"path component {} was concurrently created by another user",
component_path.display()
);
}
}
created
}
};
current.push(name);
}
Ok(directory)
}
#[cfg(unix)]
fn set_directory_metadata(
directory: &std::os::fd::OwnedFd,
owner: Option<&str>,
group: Option<&str>,View on GitHub (pinned to afd2eddd3a)
Solutions
- Re-run the command once the concurrent operation finishes; races are usually transient
- Check ownership/permissions of the parent directory — if other users can write there, restrict it (chmod/others-writable dirs invite the race)
- Ensure only one mise instance operates on the directory at a time (serialize CI jobs, avoid parallel task invocations touching the same paths)
- Investigate what replaced the path (symlink planted by another user can indicate a security issue)
Example fix
// before: parallel jobs racing on the same mise data dir // CI job A: mise install node & CI job B: mise install python & // after: serialize or lock // flock /tmp/mise.lock -c 'mise install node && mise install python'
Defensive patterns
Strategy: retry
Validate before calling
import { statSync, lstatSync } from "node:fs";
// Before running concurrent mise operations on the same data dir, check the
// path exists, is a real directory (not a symlink), and is owned by you:
function isSafeManagedDir(p: string): boolean {
try {
const st = lstatSync(p);
return st.isDirectory() && st.uid === process.getuid?.();
} catch {
return true; // not created yet is fine
}
} Type guard
function isOwnedRealDir(p: string): boolean {
try {
const st = require("node:fs").lstatSync(p);
return st.isDirectory() && !st.isSymbolicLink();
} catch { return false; }
} Try / catch
for (let attempt = 0; attempt < 3; attempt++) {
try {
await runMiseInstall();
break;
} catch (e) {
if (String(e).includes("concurrently created by another user") && attempt < 2) {
await new Promise(r => setTimeout(r, 250 * (attempt + 1)));
continue;
}
throw e;
}
} Prevention
- Serialize mise invocations that touch the same install/cache directories (flock, job queues)
- Never share a mise data directory between users without restrictive permissions
- Audit unexpected symlinks under the mise data dir — they trip this guard deliberately
- Avoid file-sync tools (Dropbox/Drive) watching the mise data directory
When it happens
Trigger: Calling any managed-files API (create/write/remove helpers in src/system/managed_files.rs) that creates parent directories component-by-component while another process or user simultaneously creates the same component, or while something replaces the just-created directory with a symlink or file between creation and open.
Common situations: Two mise processes running concurrently against the same install dir (e.g. parallel CI jobs, two shells); a shared XDG cache/data directory on a multi-user machine where another user pre-creates the path; security software or sync tools (Dropbox, antivirus) replacing paths mid-operation.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- changed while preparing recovery; left untouched
- brew-cask: refusing operation through a changed generic arti
- brew-cask: refusing operation through a changed generic arti
- expected pre-planted symlink destination to be refused
- {} changed while preparing enrollment; concurrent declaratio
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/78cea1e1f5651c78.
Report an issue: GitHub.