jdx/mise · error
managed file paths ' ' and ' ' normalize to the same target
Error message
managed file paths '{previous}' and '{path}' normalize to the same target '{}' What it means
Thrown while merging managed file declarations across config layers when two syntactically different paths normalize (via `absolute_target`) to the same absolute target file. Allowing it would make which declaration wins order-dependent, so the library rejects the ambiguity, reporting both original paths and the shared normalized target.
Solutions
- Use one canonical (usually absolute) path for the target across all layers.
- Compute the normalized target (`absolute_target`) for both reported paths and see why they collide.
- Remove the duplicate declaration or give the second file a distinct target path.
- Audit generated/template configs for path-building logic that can emit equivalent-but-different strings.
Example fix
# before [bootstrap.files."app/config.conf"] # layer A (relative) [bootstrap.files."/etc/app/config.conf"] # layer B (absolute) # after [bootstrap.files."/etc/app/config.conf"] # single canonical path
Defensive patterns
Strategy: validation
Validate before calling
import os
seen = {}
for p in all_file_paths:
t = os.path.realpath(os.path.abspath(p))
if t in seen: raise SystemExit(f'{seen[t]} and {p} normalize to {t}')
seen[t] = p Type guard
function normalize(p) { return path.resolve(p); }
function uniqueTargets(paths) {
const s = new Set(paths.map(normalize)); return s.size === paths.length;
} Prevention
- Standardize on absolute paths for managed files.
- Normalize (resolve) paths before adding them to config.
- Deduplicate generated path lists by canonical target.
When it happens
Trigger: Declaring the same file via a relative path in one layer and an absolute path in another (e.g. `config.conf` vs `/full/path/config.conf`); paths differing only by redundant `./` segments or symlink-resolving components that canonicalize to the same target.
Common situations: Configs generated by tooling that emits relative paths while hand-written layers use absolute ones; after changing working-directory assumptions, relative paths now resolve onto absolute ones declared elsewhere; duplicated entries across included config files.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- conflicting managed file declarations for
- managed directory paths
- managed system path ' ' is declared as both a file and a…
- bootstrap service ' ' cannot be both masked and running
- bootstrap service ' ' cannot be both masked and enabled
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/c59bdb7c9b28f7dc.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/managed_files.rs:427
// the nearer project declaration.
for cf in config_files.values() {
if let Some(bootstrap) = cf.bootstrap_config() {
let mut layer_paths = IndexMap::new();
let base = cf
.get_path()
.parent()
.unwrap_or_else(|| Path::new("."))
.to_path_buf();
let origin = ResourceOrigin {
config: cf.get_path().to_path_buf(),
config_root: cf.config_root(),
environment: crate::config::environments_for_config_path(cf.get_path()),
source: None,
};
for (path, file) in bootstrap.files {
let target = absolute_target(&path)?;
if let Some(previous) = layer_paths.insert(target.clone(), path.clone()) {
bail!(
"managed file paths '{previous}' and '{path}' normalize to the same target '{}'",
target.display()
);
}
let mut file_origin = origin.clone();
file_origin.source = file
.source
.as_deref()
.map(|source| resolve_source_path(&base, source));
merged
.entry(target)
.or_insert_with(|| (file, base.clone(), file_origin));
}
}
}
Ok(merged)
}
View on GitHub (pinned to 533346cc37)