jdx/mise · error

file ' ' cannot be present while managed parent ' ' is…

Error message

file '{}' cannot be present while managed parent '{}' is absent

What it means

Same invariant as the directory case, applied to a managed file: the file is declared Present while its managed parent directory is declared Absent. The planner bails because the resulting plan would be contradictory (delete the parent but keep the file inside it).

Solutions

  1. Mark the parent directory Present, or drop its Absent declaration
  2. Mark the file Absent as well if the whole subtree is meant to be removed
  3. Move the managed file to a directory that is actually kept

Example fix

// before
{"dir": "/etc/myapp", "state": "absent"}
{"file": "/etc/myapp/app.conf", "state": "present"}
// after
{"dir": "/etc/myapp", "state": "present"}
{"file": "/etc/myapp/app.conf", "state": "present"}
Defensive patterns

Strategy: validation

Validate before calling

const dirStates = new Map(dirs.map(d => [d.path, d.state]));
for (const f of files) {
  const parent = dirname(f.path);
  if (f.state === 'present' && dirStates.get(parent) === 'absent') throw new Error(`file ${f.path} present but parent ${parent} absent`);
}

Type guard

function fileParentsValid(files, dirStates) { return files.every(f => f.state !== 'present' || dirStates.get(dirname(f.path)) !== 'absent'); }

Try / catch

try { plan = planner.plan(); } catch (e) { if (String(e).includes("file '") && e.message.includes('managed parent')) { fixFileParentDeclarations(config); } else throw e; }

Prevention

When it happens

Trigger: Calling plan with a file resource in ManagedState::Present whose resolved parent directory resource is in ManagedState::Absent.

Common situations: A cleanup config removes a directory while an unrelated block still manages a file inside it; someone set the directory to absent expecting its managed file to be relocated; layered config files disagree about the parent.

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/46581fade5f75f20. Report an issue: GitHub.

Appendix: source

Thrown at src/system/resources.rs:534

            let parent_id = ResourceId::new("directory", parent.to_string_lossy());
            match (file.state, parent_state) {
                (
                    super::managed_files::ManagedState::Present,
                    super::managed_files::ManagedState::Present,
                ) => {
                    plan.add_dependency(&id, parent_id)?;
                }
                (
                    super::managed_files::ManagedState::Absent,
                    super::managed_files::ManagedState::Absent,
                ) => {
                    plan.add_dependency(&parent_id, id)?;
                }
                (
                    super::managed_files::ManagedState::Present,
                    super::managed_files::ManagedState::Absent,
                ) => {
                    bail!(
                        "file '{}' cannot be present while managed parent '{}' is absent",
                        file.path.display(),
                        parent.display()
                    );
                }
                (
                    super::managed_files::ManagedState::Absent,
                    super::managed_files::ManagedState::Present,
                ) => {}
            }
        }
    }
    for resource in unavailable_files {
        plan.insert(resource)?;
    }
    let builtin_packages = super::packages_from_config(config)
        .into_iter()
        .filter(|packages| !packages.manager.is_plugin())

View on GitHub (pinned to 533346cc37)