jdx/mise · error · eyre::Report

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 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.

Solutions

  1. Set the ancestor directory's state to "present" so the child can exist.
  2. Change the child file's state to "absent" or remove its entry, since the tree is being removed anyway.
  3. Move the file outside the Absent-managed subtree if it must persist.

Example fix

# before
[bootstrap.directories]
"/opt/legacy" = { state = "absent" }

[bootstrap.files]
"/opt/legacy/keep.conf" = { content = "...", state = "present" }

# after
[bootstrap.files]
"/etc/keep.conf" = { content = "...", state = "present" }
Defensive patterns

Strategy: validation

Validate before calling

// fail fast if any present file sits under an absent-managed directory
fn check_absent_ancestors(files: &[PathBuf], absent_dirs: &std::collections::HashSet<PathBuf>) -> Result<(), String> {
    for f in files {
        for anc in f.ancestors().skip(1) {
            if absent_dirs.contains(anc) {
                return Err(format!("{} present under absent {}", f.display(), anc.display()));
            }
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: 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".

Common situations: 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.

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


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/f6c23d4e6329e831. Report an issue: GitHub.

Appendix: source

Thrown at src/system/managed_files.rs:573

        }
    }
    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,
        origin: ResourceOrigin,
        secrets: &super::secrets::SecretValues,
    ) -> Result<Self> {
        let owner = nonempty("owner", config.owner)?;

View on GitHub (pinned to 533346cc37)