jdx/mise · error
lockfile {} changed while the format upgrade was being prepa
Error message
lockfile {} changed while the format upgrade was being prepared; retry `mise lock --upgrade` What it means
To upgrade the lockfile format safely, mise stages writes for all affected lockfiles and, just before committing them, re-reads each file to confirm it still matches the content captured when the upgrade was prepared. If any file changed in between, this error is thrown to avoid clobbering concurrent modifications; the user is told to retry.
Source
Thrown at src/cli/lock.rs:674
.map(|staged| staged.path.clone())
.chain(
migration_paths
.iter()
.flat_map(|(source, target)| [source.clone(), target.clone()]),
)
.collect();
let mut transaction_locks = Vec::with_capacity(transaction_paths.len());
for path in &transaction_paths {
transaction_locks.push(
crate::lock_file::LockFile::new(path)
.with_callback(|l| debug!("waiting for lock on {}", display_path(l)))
.lock()?,
);
}
for staged in &staged_upgrade_writes {
if read_optional_file(&staged.path)? != staged.original_content {
bail!(
"lockfile {} changed while the format upgrade was being prepared; retry `mise lock --upgrade`",
display_path(&staged.path)
);
}
}
let snapshots = transaction_paths
.iter()
.map(|path| {
Ok(LockfileSnapshot {
path: path.clone(),
content: read_optional_file(path)?,
})
})
.collect::<Result<Vec<_>>>()?;
// Materialize and sync every rollback replacement before the first
// mutation. Recovery then only needs same-directory renames, so a
// later disk-full failure cannot prevent restoration by requiringView on GitHub (pinned to afd2eddd3a)
Solutions
- Simply retry `mise lock --upgrade` once no other mise/editor process is running — the message says exactly this.
- Close IDE plugins or background tasks that rewrite mise config files while the upgrade runs.
- If a specific lockfile keeps changing, commit or stash local changes first so nothing rewrites it.
- Run the upgrade on a clean working tree to eliminate concurrent writers.
Defensive patterns
Strategy: retry
Validate before calling
git status --porcelain -- '**/mise.lock' # check no concurrent writers before upgrading
Try / catch
# shell for i in 1 2 3; do mise lock --upgrade && break sleep 2 done
Prevention
- Don't run `mise lock --upgrade` while editors, CI, or other shells run mise commands in the same tree.
- Commit or stash pending lockfile changes first so nothing rewrites them mid-upgrade.
- Pause IDE mise integrations that auto-write config files.
- Retry once on this error, as the message suggests — it is a transient conflict.
When it happens
Trigger: Run `mise lock --upgrade` in a directory tree where another process (editor, `mise install`, another mise instance, git checkout) modifies one of the staged lockfiles between the prepare phase and the final write, so `read_optional_file(&staged.path)` no longer equals `staged.original_content`.
Common situations: Running `mise lock --upgrade` while an IDE with mise integration auto-writes mise.toml/lockfiles; two terminals running mise commands simultaneously; a background `git pull`/`git checkout` touching the lockfile mid-upgrade.
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
- locked mode requires lockfile to be enabled hint: Remove `lo
- {target_raw}: tracked in place; pass `--mode copy` after `mi
- {target_raw}: target is already managed by [dotfiles] edits;
- Cannot change version of existing tool stub from {} to {}
- {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/320b3fc7c6009db7.
Report an issue: GitHub.