{"record":{"id":"320b3fc7c6009db7","repo":"jdx/mise","slug":"lockfile-changed-while-the-format-upgrade-was-b","errorCode":null,"errorMessage":"lockfile {} changed while the format upgrade was being prepared; retry `mise lock --upgrade`","messagePattern":"lockfile (.+?) changed while the format upgrade was being prepared; retry `mise lock --upgrade`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/lock.rs","lineNumber":674,"sourceCode":"                .map(|staged| staged.path.clone())\n                .chain(\n                    migration_paths\n                        .iter()\n                        .flat_map(|(source, target)| [source.clone(), target.clone()]),\n                )\n                .collect();\n            let mut transaction_locks = Vec::with_capacity(transaction_paths.len());\n            for path in &transaction_paths {\n                transaction_locks.push(\n                    crate::lock_file::LockFile::new(path)\n                        .with_callback(|l| debug!(\"waiting for lock on {}\", display_path(l)))\n                        .lock()?,\n                );\n            }\n\n            for staged in &staged_upgrade_writes {\n                if read_optional_file(&staged.path)? != staged.original_content {\n                    bail!(\n                        \"lockfile {} changed while the format upgrade was being prepared; retry `mise lock --upgrade`\",\n                        display_path(&staged.path)\n                    );\n                }\n            }\n\n            let snapshots = transaction_paths\n                .iter()\n                .map(|path| {\n                    Ok(LockfileSnapshot {\n                        path: path.clone(),\n                        content: read_optional_file(path)?,\n                    })\n                })\n                .collect::<Result<Vec<_>>>()?;\n            // Materialize and sync every rollback replacement before the first\n            // mutation. Recovery then only needs same-directory renames, so a\n            // later disk-full failure cannot prevent restoration by requiring","sourceCodeStart":656,"sourceCodeEnd":692,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/cli/lock.rs#L656-L692","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"git status --porcelain -- '**/mise.lock'  # check no concurrent writers before upgrading","typeGuard":null,"tryCatchPattern":"# shell\nfor i in 1 2 3; do\n  mise lock --upgrade && break\n  sleep 2\ndone","preventionTips":["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."],"tags":["lockfile","concurrency","cli","conflict"],"backgroundTag":"invalid-state-transition","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}