jdx/mise · error

nothing can be applied until the held paths are decided

Error message

nothing can be applied until the held paths are decided

What it means

When the incoming plan holds paths (files that cannot be applied, e.g. blocked by unresolved side conditions), an interactive apply cannot safely write anything, so it aborts with this error telling you the held paths must be decided first. The automatic watcher mode tolerates holds and just reports a count.

Source

Thrown at src/system/history/sync/apply.rs:429

        ]);
    }
    if !req.automatic {
        table.print()?;
    }
    if req.dry_run {
        if !req.plan_only {
            miseprintln!("history: dry run; nothing was changed");
        }
        return Ok(ApplyOutcome::default());
    }
    if ready.is_empty() && !((fresh_adoption || inventory_tree.is_some()) && held.is_empty()) {
        if req.automatic {
            return Ok(ApplyOutcome {
                held: held.len(),
                ..Default::default()
            });
        }
        bail!("nothing can be applied until the held paths are decided");
    }
    if !req.automatic
        && !super::origin::confirmed(req.yes, "history: apply these incoming changes?")?
    {
        info!("history: skipped");
        return Ok(ApplyOutcome::default());
    }

    // the transaction
    let reload = crate::system::history::config::reload_commands()?;
    let scope = if req.automatic {
        OperationScope::begin_automatic_apply().await?
    } else {
        OperationScope::begin_kind(OperationKind::Apply, "dotfiles pull", false).await?
    };
    scope.with_operation(|op| {
        op.applied = status.upstream_commit.clone();
    });

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Inspect the held paths (dry-run or the sync status) and resolve each one with --take-remote/--keep-local or the indicated action.
  2. Use the automatic mode or --yes only when you intend holds to be tolerated rather than fatal.
  3. Clear stale status (complete or discard the pending plan) and retry the pull.

Example fix

# before
mise bootstrap dotfiles pull   # held paths block everything
# after: resolve the holds first
mise bootstrap dotfiles pull --dry-run
mise bootstrap dotfiles pull --take-remote <held-path>
Defensive patterns

Strategy: try-catch

Validate before calling

# inspect held paths before applying
mise bootstrap dotfiles pull --dry-run

Try / catch

try {
  await pull({});
} catch (e) {
  if (/nothing can be applied until the held paths are decided/.test(e.message)) {
    await resolveHeldPaths(); // take-remote/keep-local for each held path
    await pull({});
  } else throw e;
}

Prevention

When it happens

Trigger: Running apply interactively (not automatic, not dry-run) while `held` is non-empty; the apply function reaches the post-planning check and no --yes/confirmation path applies because planning produced held paths that block the whole batch.

Common situations: Unresolved conflicts or undecidable paths from a previous pull still pending; a mixed batch where one problematic file blocks all other ready changes; running the command manually after the background watcher had been holding paths.

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


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/55dd861feecdd7f9. Report an issue: GitHub.