{"record":{"id":"543f4dfe2869a511","repo":"jdx/mise","slug":"bootstrap-resource-depends-on-missing-resourc","errorCode":null,"errorMessage":"bootstrap resource '{}' depends on missing resource '{}'","messagePattern":"bootstrap resource '(.+?)' depends on missing resource '(.+?)'","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/resources.rs","lineNumber":171,"sourceCode":"        Ok(BootstrapPlanOutput { resources, summary })\n    }\n\n    fn ordered(&self) -> Result<Vec<&ResourcePlan>> {\n        let mut incoming = self\n            .resources\n            .keys()\n            .cloned()\n            .map(|id| (id, 0_usize))\n            .collect::<IndexMap<_, _>>();\n        let mut outgoing: HashMap<ResourceId, Vec<ResourceId>> = HashMap::new();\n\n        for resource in self.resources.values() {\n            for dependency in &resource.depends_on {\n                let Some(count) = incoming.get_mut(&resource.id) else {\n                    unreachable!(\"every resource was added to incoming\")\n                };\n                if !self.resources.contains_key(dependency) {\n                    bail!(\n                        \"bootstrap resource '{}' depends on missing resource '{}'\",\n                        resource.id,\n                        dependency\n                    );\n                }\n                *count += 1;\n                outgoing\n                    .entry(dependency.clone())\n                    .or_default()\n                    .push(resource.id.clone());\n            }\n        }\n\n        let mut ready = incoming\n            .iter()\n            .filter_map(|(id, count)| (*count == 0).then_some(id.clone()))\n            .collect::<VecDeque<_>>();\n        let mut ordered = Vec::with_capacity(self.resources.len());","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/resources.rs#L153-L189","documentation":"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.","triggerScenarios":"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.","commonSituations":"Config referencing a resource that a disabled manager or excluded section would have provided; adapters emitting dependency edges for optional resources without checking presence.","solutions":["Declare the missing resource named in the message, or remove the dependency on it","If the dependency is conditional, filter it out of depends_on before insert when the target is absent","Dump the plan (JSON output) and confirm the exact `kind:name` ids that exist — the reference must match exactly, including case"],"exampleFix":"// before\nlet mut plan = ResourcePlan::new(id, cur, want, action);\nplan.depends_on.push(ResourceId::new(\"user\", \"alice\")); // alice never inserted\nbootstrap_plan.insert(plan)?;\n\n// after\nif users.contains_key(\"alice\") {\n    plan.depends_on.push(ResourceId::new(\"user\", \"alice\"));\n}\nbootstrap_plan.insert(plan)?;","handlingStrategy":"validation","validationCode":"// filter depends_on to resources that will actually be inserted\nlet valid_ids: std::collections::HashSet<&ResourceId> = declared.values().map(|r| &r.id).collect();\nfor resource in declared {\n    resource.depends_on.retain(|dep| valid_ids.contains(dep));\n    plan.insert(resource)?;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call plan.output() (as plan() itself does) before serializing — it validates all references and cycles","When a dependency refers to an optional resource, add the edge only when that resource was declared","Keep dependency ids as exact `kind:name` pairs matching declared resources — case-sensitive"],"tags":["mise","bootstrap","resources","dependencies","plan"],"backgroundTag":"missing-dependency-declaration","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}