jdx/mise · error · eyre::Report

bootstrap resource '{}' depends on missing resource '{}'

Error message

bootstrap resource '{}' depends on missing resource '{}'

What it means

BootstrapPlan::ordered() — invoked via output(), which plan() always calls at the end for validation — walks every resource's depends_on list and bails if an entry refers to a resource id that was never inserted. Unlike the add_dependency guard (which checks only the dependent side at edge-creation time), this validates the dependency side and also catches plans whose ResourcePlans were inserted with depends_on pre-populated.

Source

Thrown at src/system/resources.rs:171

        Ok(BootstrapPlanOutput { resources, summary })
    }

    fn ordered(&self) -> Result<Vec<&ResourcePlan>> {
        let mut incoming = self
            .resources
            .keys()
            .cloned()
            .map(|id| (id, 0_usize))
            .collect::<IndexMap<_, _>>();
        let mut outgoing: HashMap<ResourceId, Vec<ResourceId>> = HashMap::new();

        for resource in self.resources.values() {
            for dependency in &resource.depends_on {
                let Some(count) = incoming.get_mut(&resource.id) else {
                    unreachable!("every resource was added to incoming")
                };
                if !self.resources.contains_key(dependency) {
                    bail!(
                        "bootstrap resource '{}' depends on missing resource '{}'",
                        resource.id,
                        dependency
                    );
                }
                *count += 1;
                outgoing
                    .entry(dependency.clone())
                    .or_default()
                    .push(resource.id.clone());
            }
        }

        let mut ready = incoming
            .iter()
            .filter_map(|(id, count)| (*count == 0).then_some(id.clone()))
            .collect::<VecDeque<_>>();
        let mut ordered = Vec::with_capacity(self.resources.len());

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Declare the missing resource named in the message, or remove the dependency on it
  2. If the dependency is conditional, filter it out of depends_on before insert when the target is absent
  3. Dump the plan (JSON output) and confirm the exact `kind:name` ids that exist — the reference must match exactly, including case

Example fix

// before
let mut plan = ResourcePlan::new(id, cur, want, action);
plan.depends_on.push(ResourceId::new("user", "alice")); // alice never inserted
bootstrap_plan.insert(plan)?;

// after
if users.contains_key("alice") {
    plan.depends_on.push(ResourceId::new("user", "alice"));
}
bootstrap_plan.insert(plan)?;
Defensive patterns

Strategy: validation

Validate before calling

// filter depends_on to resources that will actually be inserted
let valid_ids: std::collections::HashSet<&ResourceId> = declared.values().map(|r| &r.id).collect();
for resource in declared {
    resource.depends_on.retain(|dep| valid_ids.contains(dep));
    plan.insert(resource)?;
}

Prevention

When it happens

Trigger: A ResourcePlan inserted with a depends_on entry naming an id that is not in the plan (e.g. an account, file, or directory that was filtered out because its manager was unavailable or its section disabled); compose projects have their own earlier-specific message, so this generic one fires for the remaining wiring.

Common situations: Config referencing a resource that a disabled manager or excluded section would have provided; adapters emitting dependency edges for optional resources without checking presence.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/543f4dfe2869a511. Report an issue: GitHub.