{"record":{"id":"0358774acc972c0a","repo":"tinyhumansai/openhuman","slug":"timed-out-waiting-for-auth-profile-lock","errorCode":null,"errorMessage":"Timed out waiting for auth profile lock","messagePattern":"Timed out waiting for auth profile lock","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/security/credentials/profiles.rs","lineNumber":1216,"sourceCode":"        // (2) it lets us treat an on-disk lock recording our own pid as a leaked\n        // `Drop` unlink and reclaim it immediately — no other thread in this\n        // process can hold a live guard while we own this in-memory lock (see\n        // `reclaim_self_owned_lock`). Held for the lifetime of the returned\n        // guard.\n        //\n        // Use `try_lock` against the *same* `LOCK_TIMEOUT_MS` budget as the\n        // on-disk wait rather than a blocking `lock()`: a wedged in-process\n        // holder must not be able to strand an RPC/blocking worker past the\n        // timeout the caller (e.g. `app_state_snapshot`) expects. Poison is\n        // recoverable — the `()` payload carries no invariant.\n        let in_process_lock = in_process_lock_for(&self.lock_path);\n        let in_process_guard = loop {\n            match in_process_lock.try_lock() {\n                Ok(guard) => break guard,\n                Err(TryLockError::Poisoned(poisoned)) => break poisoned.into_inner(),\n                Err(TryLockError::WouldBlock) => {\n                    if started_at.elapsed().as_millis() as u64 >= LOCK_TIMEOUT_MS {\n                        anyhow::bail!(\"Timed out waiting for auth profile lock\");\n                    }\n                    thread::sleep(Duration::from_millis(LOCK_WAIT_MS));\n                }\n            }\n        };\n\n        let mut cleared_stale = false;\n        // Periodically re-probe for stale locks during the busy-wait. A\n        // lock that started fresh (live pid, recent mtime) can age past\n        // STALE_LOCK_AGE_MS while we wait, and we want to recover from\n        // that without bailing at the LOCK_TIMEOUT_MS boundary.\n        let mut next_stale_recheck_ms: u64 = 1_000;\n        loop {\n            let open_result = crate::openhuman::util::retry_with_backoff(\n                \"create auth profile lock\",\n                6,\n                100,\n                || {","sourceCodeStart":1198,"sourceCodeEnd":1234,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/security/credentials/profiles.rs#L1198-L1234","documentation":"The bounded wait for the auth-profile store lock (in-process mutex plus on-disk lock file) expired before the lock was acquired, so the operation aborts instead of blocking the RPC/blocking worker indefinitely. It typically indicates a concurrently running core process, a slow prior store write, or a leaked on-disk lock that self-reclaim logic did not cover.","triggerScenarios":"Thrown at src/openhuman/security/credentials/profiles.rs:1216 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry the operation; transient contention usually clears within one timeout window.","Check for a second core process or CLI instance holding the profile store.","Inspect the lock file in the workspace for a stale pid; remove it only if the owning process is gone."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}