jdx/mise · error
bootstrap resource dependency cycle
Error message
bootstrap resource dependency cycle: {cycle} What it means
During bootstrap planning, the provisioner topologically sorts declared resources by their dependencies. If the sort yields fewer resources than were declared, a dependency cycle exists among the resources listed in the message. The library refuses to order (and therefore provision) a plan it can never execute.
Solutions
- Inspect the resource IDs listed in the error message and find the mutual/transitive dependency among them
- Remove or reverse one dependency edge so the graph becomes a DAG
- Split the cyclic group into independently ordered resources with a one-directional dependency
- Ensure explicit_dependencies only reference resources that cannot reference back
Example fix
// before
dir_a.depends_on("dir:b");
dir_b.depends_on("dir:a");
// after
dir_b.depends_on("dir:a"); // one direction only Defensive patterns
Strategy: validation
Validate before calling
const ids = new Set(resources.map(r => r.id)); for (const r of resources) for (const d of r.depends_on) if (ids.has(d)) checkCycle(resources, r.id, d); // DFS for back-edges before calling the planner
Type guard
function isAcyclic(res) { const seen = new Set(), stack = new Set(); function visit(id) { if (stack.has(id)) return false; if (seen.has(id)) return true; stack.add(id); const deps = res.find(r => r.id === id)?.depends_on ?? []; for (const d of deps) if (ids.has(d) && !visit(d)) return false; stack.delete(id); seen.add(id); return true; } return res.every(r => visit(r.id)); } Prevention
- Keep dependencies one-directional: lower-level resources (users, groups, dirs) never depend on higher-level ones (files, compose projects)
- Validate the dependency graph for cycles in CI before deploying bootstrap configs
- Derive dependencies from structure (parent dirs) rather than listing them manually
When it happens
Trigger: Calling the bootstrap plan/ordered ordering code (reached via plan -> output) when two or more declared resources (directories, files, users, groups, compose projects) depend on each other, directly or transitively, e.g. directory A depends on B and B depends on A.
Common situations: Hand-written resource manifests where a directory declares a parent that itself declares a dependency back on the child; copy-pasted resource blocks with swapped dependency directions; a compose project and a directory each listing the other in explicit_dependencies.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- absent bootstrap group
- absent bootstrap user
- automatic cross-platform provisioning is unavailable from a…
- bootstrap_command left multiple
- bootstrap_command left multiple unchanged mise executables…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/48e8b1fab11cfb9a.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/resources.rs:317
for dependent in dependents {
let count = incoming
.get_mut(dependent)
.expect("dependent resource is present");
*count -= 1;
if *count == 0 {
ready.push_back(dependent.clone());
}
}
}
}
if ordered.len() != self.resources.len() {
let cycle = incoming
.into_iter()
.filter_map(|(id, count)| (count > 0).then_some(id.to_string()))
.collect::<Vec<_>>()
.join(", ");
bail!("bootstrap resource dependency cycle: {cycle}");
}
Ok(ordered)
}
}
/// Build the resource plan currently supported by the provisioning engine.
/// Other bootstrap sections will move into this graph as resource adapters land.
pub(crate) async fn plan(
config: &Config,
secrets: &super::secrets::SecretValues,
) -> Result<BootstrapPlan> {
let mut plan = BootstrapPlan::default();
let accounts = super::accounts::prepare_requests_from_config(config)?;
let group_states = accounts
.groups
.iter()
.map(|group| (group.name.clone(), group.state))
.collect::<HashMap<_, _>>();View on GitHub (pinned to 533346cc37)