jdx/mise · error
managed path '{}' cannot be present while managed ancestor '
Error message
managed path '{}' cannot be present while managed ancestor '{}' is absent What it means
validate_present_ancestors (managed_files.rs:413-427) enforces state consistency up the directory tree: a resource declared `state = "present"` may not have any managed ancestor directory declared `state = "absent"`. It scans path.ancestors() (skipping the path itself) against the directory_states map and bails on the first absent ancestor. This runs for every file and directory request during validate_requests and in the secret-unavailable branch (603).
Source
Thrown at src/system/managed_files.rs:420
validate_present_ancestors(&directory.path, directory.state, &directory_states)?;
}
Ok(())
}
fn validate_present_ancestors(
path: &Path,
state: ManagedState,
directory_states: &std::collections::HashMap<&Path, ManagedState>,
) -> Result<()> {
if state != ManagedState::Present {
return Ok(());
}
if let Some(parent) = path
.ancestors()
.skip(1)
.find(|parent| directory_states.get(parent) == Some(&ManagedState::Absent))
{
bail!(
"managed path '{}' cannot be present while managed ancestor '{}' is absent",
path.display(),
parent.display()
);
}
Ok(())
}
impl ManagedFileRequest {
fn from_toml(
root_config: &Config,
path: PathBuf,
config: ManagedFileTomlConfig,
base: &Path,
secrets: &super::secrets::SecretValues,
) -> Result<Self> {
let owner = nonempty("owner", config.owner)?;
let group = nonempty("group", config.group)?;View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Flip the ancestor directory to `state = "present"` if its contents should exist
- Move the present file/directory outside the absent ancestor's subtree (different path)
- Make the child `state = "absent"` too — removing the parent removes the child anyway, so an explicit absent child entry can be deleted entirely
Example fix
# before [bootstrap.directories."/etc/legacy"] state = "absent" recursive = true [bootstrap.files."/etc/legacy/keep.conf"] content = "keep" # after — keep.conf relocated out of the removed tree [bootstrap.directories."/etc/legacy"] state = "absent" recursive = true [bootstrap.files."/etc/keep.conf"] content = "keep"
Defensive patterns
Strategy: validation
Validate before calling
// Reject present-under-absent-ancestor before planning
let absent_dirs: HashSet<_> = merged_dirs(config).iter().filter(|d| d.state == Absent).map(|d| d.path.clone()).collect();
for r in all_present_resources(config) {
for ancestor in r.path.ancestors().skip(1) {
assert!(!absent_dirs.contains(ancestor), "{} is present under absent ancestor {}", r.path.display(), ancestor.display());
}
} Prevention
- Before marking a directory absent, sweep every config layer for present children under it
- Removing a parent makes explicit child removals redundant — delete child entries when the tree goes
- Keep remove-trees and keep-files in disjoint subtrees from the start
When it happens
Trigger: `[bootstrap.directories."/etc/legacy"] state = "absent"` together with `[bootstrap.files."/etc/legacy/app.conf"] state = "present"`; or absent directory `/opt/stack` with present directory `/opt/stack/sub`. Any present path whose parent, grandparent, ... is a managed-absent directory errors — even when the absent ancestor is several levels up.
Common situations: Cleaning up a tree with absent while keeping one config file inside it; layered configs where one layer removes a directory another layer populates; ordering assumptions ('the file is written before the directory is removed') — mise does not order around this, it forbids it.
Related errors
- managed system path '{}' is declared as both a file and a di
- managed file paths '{previous}' and '{path}' normalize to th
- managed directory paths '{previous}' and '{path}' normalize
- [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/f6c23d4e6329e831.
Report an issue: GitHub.