{"record":{"id":"b61407e313a05f5d","repo":"jdx/mise","slug":"another-history-operation-is-running","errorCode":null,"errorMessage":"another history operation is running","messagePattern":"another history operation is running","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/system/history/scope.rs","lineNumber":704,"sourceCode":"    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);\n    };\n    Ok(lock)\n}\n\n/// How long an operation waits for a running one, and how often it looks.\nconst OPERATION_LOCK_WAIT: std::time::Duration = std::time::Duration::from_secs(30);","sourceCodeStart":686,"sourceCodeEnd":722,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/scope.rs#L686-L722","documentation":"Contention failure in acquire_operation_lock: another history operation (e.g. the watcher applying incoming changes) holds the operation lock in the state dir and did not release it within the bounded wait, so the new operation refuses to proceed to avoid concurrent mutation.","triggerScenarios":"Lock held past deadline and store::read_marker_in returned None — the holder is an older/foreign process that did not write a marker, or the marker was deleted while the lock is held.","commonSituations":"Mixed mise versions sharing a state dir; marker file removed manually; lock held by a non-mise tool that created the same lock file.","solutions":["Wait and retry once the other operation finishes (it is usually brief)","Check the state dir marker to identify the running operation and whether it is wedged","Remove a stale lock only after confirming no history process is alive"],"exampleFix":"# find who holds the lock\nlsof \"$MISE_STATE_DIR\"/history/lock\n# if stale:\nrm \"$MISE_STATE_DIR\"/history/lock","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match history_op() {\n    Err(e) if e.to_string().contains(\"another history operation is running\") => {\n        if lock_holder_dead() { remove_stale_lock(); retry(); } else { wait(); }\n    }\n    other => other,\n}","preventionTips":["Use the same mise version everywhere so markers are always written","Never manually delete marker files while operations may be live","Use lsof to confirm a lock is stale before removing it"],"tags":["lock","concurrency","stale-lock","history"],"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-14T05:17:10.506Z"}