tinyhumansai/openhuman · error

Timed out waiting for auth profile lock

Error message

Timed out waiting for auth profile lock

What it means

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.

Source

Thrown at src/openhuman/security/credentials/profiles.rs:1216

        // (2) it lets us treat an on-disk lock recording our own pid as a leaked
        // `Drop` unlink and reclaim it immediately — no other thread in this
        // process can hold a live guard while we own this in-memory lock (see
        // `reclaim_self_owned_lock`). Held for the lifetime of the returned
        // guard.
        //
        // Use `try_lock` against the *same* `LOCK_TIMEOUT_MS` budget as the
        // on-disk wait rather than a blocking `lock()`: a wedged in-process
        // holder must not be able to strand an RPC/blocking worker past the
        // timeout the caller (e.g. `app_state_snapshot`) expects. Poison is
        // recoverable — the `()` payload carries no invariant.
        let in_process_lock = in_process_lock_for(&self.lock_path);
        let in_process_guard = loop {
            match in_process_lock.try_lock() {
                Ok(guard) => break guard,
                Err(TryLockError::Poisoned(poisoned)) => break poisoned.into_inner(),
                Err(TryLockError::WouldBlock) => {
                    if started_at.elapsed().as_millis() as u64 >= LOCK_TIMEOUT_MS {
                        anyhow::bail!("Timed out waiting for auth profile lock");
                    }
                    thread::sleep(Duration::from_millis(LOCK_WAIT_MS));
                }
            }
        };

        let mut cleared_stale = false;
        // Periodically re-probe for stale locks during the busy-wait. A
        // lock that started fresh (live pid, recent mtime) can age past
        // STALE_LOCK_AGE_MS while we wait, and we want to recover from
        // that without bailing at the LOCK_TIMEOUT_MS boundary.
        let mut next_stale_recheck_ms: u64 = 1_000;
        loop {
            let open_result = crate::openhuman::util::retry_with_backoff(
                "create auth profile lock",
                6,
                100,
                || {

View on GitHub (pinned to 7491200858)

Solutions

  1. Retry the operation; transient contention usually clears within one timeout window.
  2. Check for a second core process or CLI instance holding the profile store.
  3. Inspect the lock file in the workspace for a stale pid; remove it only if the owning process is gone.
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at src/openhuman/security/credentials/profiles.rs:1216 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/0358774acc972c0a. Report an issue: GitHub.