jdx/mise · error
managed directory paths '{previous}' and '{path}' normalize
Error message
managed directory paths '{previous}' and '{path}' normalize to the same target '{}' What it means
Same-layer duplicate detection as error 604, but for the `[bootstrap.directories]` table: two directory entries in one config file whose declared paths normalize to the same absolute target via absolute_target() (managed_files.rs:364-371). Because directory entries carry owner/group/mode/state, two conflicting declarations cannot be merged field-wise, so mise refuses rather than picking one arbitrarily.
Source
Thrown at src/system/managed_files.rs:369
target.display()
);
}
merged.entry(target).or_insert_with(|| (file, base.clone()));
}
}
}
Ok(merged)
}
fn directories_from_config(config: &Config) -> Result<Vec<ManagedDirectoryRequest>> {
let mut merged: IndexMap<PathBuf, ManagedDirectoryTomlConfig> = IndexMap::new();
for cf in config.config_files.values() {
if let Some(bootstrap) = cf.bootstrap_config() {
let mut layer_paths = IndexMap::new();
for (path, directory) in bootstrap.directories {
let target = absolute_target(&path)?;
if let Some(previous) = layer_paths.insert(target.clone(), path.clone()) {
bail!(
"managed directory paths '{previous}' and '{path}' normalize to the same target '{}'",
target.display()
);
}
merged.entry(target).or_insert(directory);
}
}
}
merged
.into_iter()
.map(|(path, config)| ManagedDirectoryRequest::from_toml(path, config))
.collect()
}
fn validate_requests(
files: &[ManagedFileRequest],
directories: &[ManagedDirectoryRequest],
) -> Result<()> {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Delete one of the colliding entries and keep the fully-specified one
- Normalize path spellings to absolute paths throughout the table to make future collisions obvious at a glance
- If duplicate intent was layering (base + override), split the entries across different config files so the merge logic (later layer wins) applies
Example fix
# before [bootstrap.directories."/srv/app"] owner = "app" [bootstrap.directories."/srv/./app"] owner = "app" # after [bootstrap.directories."/srv/app"] owner = "app"
Defensive patterns
Strategy: validation
Validate before calling
// Same check as 604 but for the directories table
let mut seen = HashSet::new();
for key in bootstrap_directories_keys(config_file) {
let t = absolute(base_dir, normalize(key));
assert!(seen.insert(t), "duplicate directory target in this config file");
} Prevention
- Prefer absolute paths in [bootstrap.directories]
- When generating directories programmatically, key the generator on the normalized path, not the raw string
- CI lint: fail on normalized-path duplicates within each layer
When it happens
Trigger: A single mise.toml with `[bootstrap.directories."/srv/app"]` and `[bootstrap.directories."/srv/./app"]` (or `"srv/app"` and `"./srv/app"` relative to the config dir) — string-distinct keys whose normalized absolute targets are identical.
Common situations: Generated config emitted by templates that join paths inconsistently (with/without leading `./` or redundant separators); incrementally appended entries during bootstrap development where the earlier spelling was forgotten; refactors that changed from relative to absolute paths without removing old entries.
Related errors
- managed file paths '{previous}' and '{path}' normalize to th
- managed system path '{}' is declared as both a file and a di
- managed path '{}' cannot be present while managed ancestor '
- [bootstrap.files]."{}": source and content are mutually excl
- [bootstrap.files]."{}": present files require source or cont
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/323b7ddc813a5309.
Report an issue: GitHub.