jdx/mise · error
global configuration directory must not be a symlink
Error message
global configuration directory must not be a symlink
What it means
The destination global configuration directory must be a real directory; if it is a symlink, install refuses to avoid writing configuration through a link to an unexpected location (security/integrity guard).
Source
Thrown at src/system/remote_repository.rs:194
&global_directory(),
)
}
fn install_at(
bundle: &Path,
origin: &str,
revision: &str,
update: bool,
yes: bool,
dry_run: bool,
destination: &Path,
) -> Result<PathBuf> {
validate_origin(origin)?;
if !matches!(revision.len(), 40 | 64) || !revision.bytes().all(|b| b.is_ascii_hexdigit()) {
bail!("invalid pinned revision");
}
if destination.is_symlink() {
bail!("global configuration directory must not be a symlink");
}
let parent = destination
.parent()
.ok_or_else(|| eyre::eyre!("missing parent directory"))?;
if !dry_run {
std::fs::create_dir_all(parent)?;
}
let _lock = crate::lock_file::LockFile::new(destination).lock()?;
// the checkout is renamed into place, so it is staged next to the
// destination; a dry run never renames and leaves the parent alone
let temporary = if dry_run {
tempfile::tempdir()?
} else {
tempfile::tempdir_in(parent)?
};
let checkout = temporary.path().join("checkout");
let shown = crate::file::display_path(destination);
let mut command = Command::new("git");View on GitHub (pinned to afd2eddd3a)
Solutions
- Replace the symlink with a real directory (copy contents back)
- Point the tool at a non-symlink destination path
- Install from the dotfiles repository itself rather than symlinking the config dir
Example fix
# before ~/.config/mise -> ~/dotfiles/mise # after $ rm ~/.config/mise && cp -r ~/dotfiles/mise ~/.config/mise
Defensive patterns
Strategy: validation
Validate before calling
fn dest_is_real_dir(p: &Path) -> bool {
!p.is_symlink() && p.is_dir()
} Prevention
- Do not symlink the global config directory into dotfiles repos; use a real dir plus a managed sync mechanism
- Check `ls -la` on the config path before onboarding
- If using dotfiles managers, have them manage files, not the directory itself
When it happens
Trigger: Calling install_at / install / install_source / preview_source where destination.is_symlink() is true — e.g. ~/.config/mise replaced by a symlink to a dotfiles repo or synced folder.
Common situations: Users symlinking their config dir into a git-managed dotfiles tree, or sync tools (Dropbox etc.) that replaced the directory with a link.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- too many symbolic links in managed directory {}
- refusing to resolve managed directory {} to the filesystem r
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
- failed to create file symlink: {err}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/e0a4b491a5753a55.
Report an issue: GitHub.