jdx/mise · error

{}

Error message

{}

What it means

`mise lock` restores per-tool lockfile snapshot entries; each failed restore is collected and, if any errors occurred, they are joined with newlines and raised as a single bail. The message content is whatever the individual restore failures reported, so this error surfaces aggregate lockfile-restore failures after all tasks have run.

Source

Thrown at src/cli/lock.rs:252

    let mut errors = Vec::new();
    for rollback in rollbacks.into_iter().rev() {
        let result = match rollback.replacement {
            Some(replacement) => replacement.commit(),
            None => match fs::remove_file(&rollback.path) {
                Ok(()) => Ok(()),
                Err(err) if err.kind() == ErrorKind::NotFound => Ok(()),
                Err(err) => Err(err.into()),
            },
        };
        if let Err(err) = result {
            errors.push(format!("{}: {err:?}", display_path(&rollback.path)));
        }
    }
    lockfile::invalidate_caches();
    if errors.is_empty() {
        Ok(())
    } else {
        bail!("{}", errors.join("\n"))
    }
}

#[derive(Debug, Eq, PartialEq)]
enum LockTaskStatus {
    Updated,
    Unresolved,
    Failed,
    ProvenanceFailed,
}

fn classify_lock_result(
    resolution_error: Option<String>,
    error_is_fatal: bool,
    applied: bool,
) -> (LockTaskStatus, Option<String>) {
    if let Some(error) = resolution_error.filter(|_| error_is_fatal) {
        (LockTaskStatus::Failed, Some(error))

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Read the joined error lines in the message — each line identifies the specific restore failure; fix those individually.
  2. Check write permissions on the mise config directory and lockfiles, and close editors/programs holding the files open.
  3. Ensure no other mise process is running concurrently (stale locks), then rerun `mise lock`.
  4. Restore the affected config files from version control if snapshots are corrupt, and rerun.

Example fix

// diagnose: rerun with debug to see the per-file failures
MISE_DEBUG=1 mise lock
// after fixing permission/lock issues
mise lock
Defensive patterns

Strategy: retry

Validate before calling

# shell: check writable config dir before locking
[ -w "$(dirname "$(mise where 2>/dev/null || echo ~/.config/mise)/..")" ] || chmod -R u+w ~/.config/mise
mise lock

Try / catch

# shell: inspect joined error lines, fix, then retry
if ! mise lock; then
  MISE_DEBUG=1 mise lock 2>lock.err || true
  cat lock.err   # each line is one restore failure
  # fix permissions/close editors, then:
  mise lock
fi

Prevention

When it happens

Trigger: Running `mise lock` (restore_lockfile_snapshots, invoked from run and rollback paths) when one or more snapshot restore operations fail — e.g. a snapshot file cannot be written or a replaced file cannot be restored — so errors is non-empty at the end of the function.

Common situations: Read-only filesystems or permission problems preventing snapshot writes during `mise lock`; concurrent mise processes locking the same config files; rollback paths after partially failed lock operations.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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