jdx/mise · error
refusing unsafe change to bootstrap compose project '{}'; in
Error message
refusing unsafe change to bootstrap compose project '{}'; inspect `mise bootstrap plan` What it means
`apply_with_dry_run_actions` reconciles each `[bootstrap.compose.<name>]` request against the actions recorded during dry-run/plan, refined by a fresh classification in `apply_action`. A project classified as `ResourceAction::Unknown` means mise cannot safely determine whether the deployed project matches the config, and it refuses to guess rather than risk tearing down or recreating a live project. The message points at `mise bootstrap plan` for inspection.
Source
Thrown at src/system/compose.rs:209
.map(|request| request.plan_with_dependency_change(dependency_changed))
.collect()
}
pub fn apply(requests: &[ComposeRequest], dry_run: bool, yes: bool) -> Result<()> {
apply_with_dry_run_actions(requests, &HashMap::new(), dry_run, yes)
}
pub fn apply_with_dry_run_actions(
requests: &[ComposeRequest],
dry_run_actions: &HashMap<String, ResourceAction>,
dry_run: bool,
yes: bool,
) -> Result<()> {
let mut changes = vec![];
for request in requests {
let action = apply_action(request, dry_run_actions, dry_run);
match action {
ResourceAction::Unknown => bail!(
"refusing unsafe change to bootstrap compose project '{}'; inspect `mise bootstrap plan`",
request.name
),
ResourceAction::Noop => {}
ResourceAction::Create | ResourceAction::Update | ResourceAction::Remove => {
changes.push(request)
}
}
}
if changes.is_empty() {
info!("compose projects: already converged");
return Ok(());
}
if dry_run {
for request in changes {
for argv in request.dry_run_action_argvs()? {
miseprintln!("would run {}", shell_words::join(argv));
}View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Run `mise bootstrap plan` (or `apply --dry-run`) and read the reported action for the named project — Unknown there shows classification itself failed.
- Fix the classification blocker: ensure the docker engine is reachable (and reachable under sudo if `sudo = true`), compose v2 works, and `project_dir`/`files` resolve.
- Re-run `mise bootstrap compose apply`; once every project classifies as Noop/Create/Update/Remove the refusal disappears.
Example fix
# before mise bootstrap compose apply # error: refusing unsafe change to bootstrap compose project 'web'; ... # after mise bootstrap compose plan # inspect why the project classifies as Unknown # fix engine/compose availability, then: mise bootstrap compose apply
Defensive patterns
Strategy: validation
Validate before calling
// run the plan pass first and assert every project has a known action
let plans = compose::plans(&requests);
for plan in &plans {
assert!(
!matches!(plan.action, ResourceAction::Unknown),
"project {} classifies as Unknown; fix engine/compose availability first",
plan.id.value
);
}
compose::apply_with_dry_run_actions(&requests, &dry_run_actions, dry_run, yes)?; Try / catch
match compose::apply_with_dry_run_actions(&reqs, &actions, dry_run, yes) {
Ok(()) => {}
Err(err) if err.to_string().contains("refusing unsafe change") => {
// do NOT force past it: re-run `mise bootstrap compose plan`, fix why the named
// project classifies as Unknown (engine reachable? sudo context?), then retry.
}
Err(err) => return Err(err),
} Prevention
- Always run `mise bootstrap compose plan` before apply in CI and fail on Unknown actions.
- Keep engine access identical between plan and apply (same user/sudo, same DOCKER_HOST).
When it happens
Trigger: Running apply when the dry-run/plan map has no usable entry for a project, or when live classification cannot decide (docker engine unreachable mid-run, `docker compose config` failing, state indeterminate) so `apply_action` falls back to Unknown.
Common situations: Applying right after a plan made on a different host or with the engine down; engine socket permissions differing under sudo vs the user; stale plan data after the compose file changed underneath the run.
Related errors
- bootstrap compose project '{name}' services cannot be combin
- services not found in compose config: {}
- container inspection returned an unexpected number of rows
- compose command failed with {status}
- legacy 'docker-compose' v1 is unsupported; install Docker Co
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/e75aa98195c708e8.
Report an issue: GitHub.