{"record":{"id":"f8e0f7dcf09df1dd","repo":"jdx/mise","slug":"another-history-operation-is-running-since","errorCode":null,"errorMessage":"another history operation is running: {} since {} ({})","messagePattern":"another history operation is running: (.+?) since (.+?) \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/system/history/scope.rs","lineNumber":698,"sourceCode":"pub(crate) fn recovery_lock(store: &Store) -> Result<fslock::LockFile> {\n    acquire_operation_lock(store, std::time::Duration::ZERO)\n}\n\nfn acquire_operation_lock(store: &Store, wait: std::time::Duration) -> Result<fslock::LockFile> {\n    let state_dir = store.state_dir();\n    let path = store::operation_lock_in(state_dir);\n    // a running operation (the watcher applying incoming changes, say) is\n    // usually over in moments: wait for it a bounded while before failing\n    let deadline = std::time::Instant::now() + wait;\n    let mut announced = false;\n    let lock = loop {\n        if let Some(lock) = LockFile::new(&path).try_lock()? {\n            break lock;\n        }\n        let marker = store::read_marker_in(state_dir)?;\n        if std::time::Instant::now() >= deadline {\n            match marker {\n                Some(marker) => bail!(\n                    \"another history operation is running: {} since {} ({})\",\n                    marker.kind.as_str(),\n                    marker.started_at,\n                    marker.command\n                ),\n                None => bail!(\"another history operation is running\"),\n            }\n        }\n        if !announced {\n            announced = true;\n            info!(\n                \"history: waiting for another history operation to finish{}\",\n                marker\n                    .map(|marker| format!(\": {} ({})\", marker.kind.as_str(), marker.command))\n                    .unwrap_or_default()\n            );\n        }\n        std::thread::sleep(OPERATION_LOCK_POLL);","sourceCodeStart":680,"sourceCodeEnd":716,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/scope.rs#L680-L716","documentation":"acquire_operation_lock takes an exclusive file lock for history operations. When the lock cannot be acquired before the deadline, mise reads the marker file left by the current holder and reports which operation is running, since when, and from which command, instead of deadlocking or corrupting shared state.","triggerScenarios":"A concurrent history operation (install-time checkpoint, rollback, recovery, pull apply) holds the lock past the wait deadline; or a stale lock file with a marker from a crashed process.","commonSituations":"Two mise commands in different terminals/shells at once; a crashed mise left a lock and marker behind; a long rollback still running while you start another command.","solutions":["Wait for the currently running history operation to finish, then retry","Find and terminate the stuck mise process shown in the message","If the holder is dead (stale lock), remove the lock/marker files in the state dir and retry","Retry later; mise waits and logs progress before the deadline expires"],"exampleFix":"// stale lock from crashed process\nrm \"$(mise config get state_dir 2>/dev/null || echo ~/.local/state/mise)\"/history/*.lock\n// after: rerun the command once no mise history process is alive","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match history_op() {\n    Err(e) if e.to_string().contains(\"another history operation is running\") => {\n        wait_for_lock_release(); retry_with_backoff();\n    }\n    other => other,\n}","preventionTips":["Avoid running multiple mise history commands in parallel","Check for leftover lock/marker files after crashes before retrying","Kill hung mise processes rather than force-removing live locks"],"tags":["lock","concurrency","history","busy-resource"],"backgroundTag":"address-already-in-use","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}