{"record":{"id":"f6c23d4e6329e831","repo":"jdx/mise","slug":"managed-path-cannot-be-present-while-managed","errorCode":null,"errorMessage":"managed path '{}' cannot be present while managed ancestor '{}' is absent","messagePattern":"managed path '(.+?)' cannot be present while managed ancestor '(.+?)' is absent","errorType":"error_code","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":573,"sourceCode":"        }\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 {\n        return Ok(());\n    }\n    if let Some(parent) = path\n        .ancestors()\n        .skip(1)\n        .find(|parent| directory_states.get(parent) == Some(&ManagedState::Absent))\n    {\n        bail!(\n            \"managed path '{}' cannot be present while managed ancestor '{}' is absent\",\n            path.display(),\n            parent.display()\n        );\n    }\n    Ok(())\n}\n\nimpl ManagedFileRequest {\n    fn from_toml(\n        root_config: &Config,\n        path: PathBuf,\n        config: ManagedFileTomlConfig,\n        base: &Path,\n        origin: ResourceOrigin,\n        secrets: &super::secrets::SecretValues,\n    ) -> Result<Self> {\n        let owner = nonempty(\"owner\", config.owner)?;","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/managed_files.rs#L555-L591","documentation":"validate_present_ancestors enforces logical consistency of declared states along the path hierarchy: a path declared Present cannot sit under a managed ancestor directory declared Absent, since removing the ancestor removes the child. Called from validate_requests and directly by status_requests_from_config for each present file, it scans path.ancestors() against the directory state map and bails on the first Absent ancestor.","triggerScenarios":"status_requests_from_config or validate_requests encountering a [bootstrap.files] entry with state = \"present\" whose ancestor path exists in [bootstrap.directories] with state = \"absent\".","commonSituations":"Deleting a directory tree but forgetting to flip contained file entries to absent or remove them; partially reverting a cleanup commit; templated configs where directory state is variable but file state is hardcoded.","solutions":["Set the ancestor directory's state to \"present\" so the child can exist.","Change the child file's state to \"absent\" or remove its entry, since the tree is being removed anyway.","Move the file outside the Absent-managed subtree if it must persist."],"exampleFix":"# before\n[bootstrap.directories]\n\"/opt/legacy\" = { state = \"absent\" }\n\n[bootstrap.files]\n\"/opt/legacy/keep.conf\" = { content = \"...\", state = \"present\" }\n\n# after\n[bootstrap.files]\n\"/etc/keep.conf\" = { content = \"...\", state = \"present\" }","handlingStrategy":"validation","validationCode":"// fail fast if any present file sits under an absent-managed directory\nfn check_absent_ancestors(files: &[PathBuf], absent_dirs: &std::collections::HashSet<PathBuf>) -> Result<(), String> {\n    for f in files {\n        for anc in f.ancestors().skip(1) {\n            if absent_dirs.contains(anc) {\n                return Err(format!(\"{} present under absent {}\", f.display(), anc.display()));\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When marking a directory absent, remove or flip all entries beneath it in the same change.","Prefer declaring the directory absent alone and letting recursive removal handle children.","Add a config lint that walks ancestors for every present file entry."],"tags":["config-validation","managed-files","state-consistency"],"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"}