{"record":{"id":"ab37015ef5d48958","repo":"jdx/mise","slug":"managed-path-conflicts-with-ancestor-parent-directories-must","errorCode":null,"errorMessage":"managed path '{}' ({}) conflicts with ancestor '{}' ({}): parent directories must be created before children and removed after children; adjust their phase declarations","messagePattern":"managed path '(.+?)' \\((.+?)\\) conflicts with ancestor '(.+?)' \\((.+?)\\): parent directories must be created before children and removed after children; adjust their phase declarations","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":547,"sourceCode":"        )\n    {\n        for parent in directories\n            .iter()\n            .filter(|dir| path != &dir.path && path.starts_with(&dir.path))\n        {\n            let invalid = match (state, parent.state) {\n                (ManagedState::Present, ManagedState::Present) => {\n                    phase == ManagedFilePhase::PrePackages\n                        && parent.phase == ManagedFilePhase::PostPackages\n                }\n                (ManagedState::Absent, ManagedState::Absent) => {\n                    phase == ManagedFilePhase::PostPackages\n                        && parent.phase == ManagedFilePhase::PrePackages\n                }\n                _ => false,\n            };\n            if invalid {\n                bail!(\n                    \"managed path '{}' ({}) conflicts with ancestor '{}' ({}): parent directories must be created before children and removed after children; adjust their phase declarations\",\n                    path.display(),\n                    phase.as_str(),\n                    parent.path.display(),\n                    parent.phase.as_str()\n                );\n            }\n        }\n    }\n    Ok(())\n}\n\nfn validate_present_ancestors(\n    path: &Path,\n    state: ManagedState,\n    directory_states: &std::collections::HashMap<&Path, ManagedState>,\n) -> Result<()> {\n    if state != ManagedState::Present {","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/managed_files.rs#L529-L565","documentation":"Managed paths participate in an ordering contract: an ancestor directory declared with a create/remove phase must have a phase compatible with its descendants (parents created before children, removed after children). validate_requests walks each path's ancestors and bails when the child/parent phase combination (e.g. child PostPackages, parent PrePackages, or other invalid pairings) violates that contract.","triggerScenarios":"status_requests_from_config or prepare_requests_from_config on a config where a managed path and one of its managed ancestor directories have phases whose combination fails the compatibility check (e.g. child phase PostPackages while parent phase PrePackages in an ordering-sensitive pairing).","commonSituations":"Declaring a log dir as PrePackages but files inside it as PostPackages; adding a nested file entry without updating the parent directory's phase; refactorings that reorder package installation phases.","solutions":["Change the parent directory's phase so it is created before (and removed after) its child paths.","Alternatively move the child path's phase to match or follow its parent's creation phase.","Split the declaration so conflicting paths are no longer ancestor/descendant."],"exampleFix":"# before\n[bootstrap.directories]\n\"/var/lib/app\" = { state = \"present\", phase = \"post-packages\" }\n\n[bootstrap.files]\n\"/var/lib/app/data.db\" = { state = \"absent\", phase = \"pre-packages\" }\n\n# after\n[bootstrap.directories]\n\"/var/lib/app\" = { state = \"present\", phase = \"pre-packages\" }\n\n[bootstrap.files]\n\"/var/lib/app/data.db\" = { state = \"absent\", phase = \"post-packages\" }","handlingStrategy":"validation","validationCode":"// ensure every file's managed ancestor directory has an earlier (or equal) phase\nfn check_phases(files: &[(PathBuf, Phase)], dirs: &[(PathBuf, Phase)]) -> Result<(), String> {\n    for (fpath, fphase) in files {\n        for (dpath, dphase) in dirs {\n            if fpath.starts_with(dpath) && phase_rank(dphase) > phase_rank(fphase) {\n                return Err(format!(\"{} ({:?}) precedes {} ({:?})\", dpath.display(), dphase, fpath.display(), fphase));\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Document and follow a single phase convention (dirs pre-packages, children post-packages).","Review ancestor/descendant phase pairs whenever adding nested managed paths.","Encode phase ordering in helper constructors rather than raw TOML."],"tags":["config-validation","managed-files","phase-ordering"],"backgroundTag":"conflicting-config-options","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}