jdx/mise · error

checked by the caller

Error message

checked by the caller

What it means

execute unwraps store.repo() with expect("checked by the caller"), asserting that callers (rollback, undo) have already verified the history Store has a git repository. If the repo is absent, this invariant was violated upstream and the code panics instead of returning a graceful error.

Solutions

  1. Ensure the history store repo exists before invoking rollback/undo (check and initialize it in the caller)
  2. Reinitialize the history store so its git repository is created
  3. Report the missing-repo condition as a normal error in execute instead of expect

Example fix

// before
let repo = store.repo().expect("checked by the caller");
// after
let Some(repo) = store.repo() else {
    return Err(anyhow!("history store repository not initialized; run the command that first records history"));
};
Defensive patterns

Strategy: validation

Validate before calling

// caller-side guard before undo/rollback
if !history_store_initialized() {
    eprintln!("history store not initialized; nothing to undo");
    return;
}

Type guard

fn has_repo(store: &Store) -> bool {
    store.repo().is_some()
}

Try / catch

match store.repo() {
    Some(repo) => execute_with(repo, ...),
    None => bail!("history repository missing; reinitialize history store"),
}

Prevention

When it happens

Trigger: Calling rollback or undo without a prior existence check on the history store's repository — e.g. running undo when the history directory has no git repo initialized (history disabled, fresh install, or .git removed).

Common situations: Running `mise undo` after the history store directory was deleted or corrupted; environments where history tracking was never initialized; tampered history storage.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/499f043a6e3a7c1a. Report an issue: GitHub.

Appendix: source

Thrown at src/system/history/replay.rs:398

fn sources_of(targets: &[Target]) -> Vec<OperationSource> {
    targets
        .iter()
        .map(|target| OperationSource {
            checkpoint: target.entry.checkpoint.uuid.clone(),
            paths: target.paths.iter().map(display_path).collect(),
        })
        .collect()
}

async fn execute(
    exec: Execution,
    store: &Store,
    tracked: &TrackedSet,
    entries: &[Entry],
    live: String,
) -> Result<()> {
    let repo = store.repo().expect("checked by the caller");
    let mut steps = plan(repo, &exec, &live)?;
    print_plan(&steps, &exec, tracked)?;
    if exec.dry_run {
        return Ok(());
    }
    let conflicts: Vec<&Step> = steps
        .iter()
        .filter(|step| matches!(step.action, Action::Conflict(_)))
        .collect();
    if !conflicts.is_empty() {
        // `--force` answers a type change only (and undo already forces);
        // an occupant history never captured stays a conflict whatever is
        // passed, so it is not offered where it would not help
        let type_changes = conflicts.iter().any(
            |step| matches!(&step.action, Action::Conflict(reason) if reason.contains(" became ")),
        );
        let hint = if !exec.force && type_changes {
            "; pass --force to replace a path whose type changed"

View on GitHub (pinned to 533346cc37)