xai-org/grok-build · info

Another leader already holds the lock at {}

Error message

Another leader already holds the lock at {}

What it means

run_leader detected, via crate::leader::listener_is_ready, that another process already holds the leader lock with a bound IPC socket at the given path. This is the single-instance guard of the agent: instead of fighting for leadership, this process logs and returns an error so the caller exits and the client adopts the existing leader. It is an expected, by-design outcome of launching a second agent instance, not a fault.

Source

Thrown at crates/codegen/xai-grok-shell/src/agent/app.rs:791

    });
    let mut agent_config = agent_config.clone();
    agent_config.mode = crate::agent::config::AgentMode::Leader;
    let ws_url = &agent_config.grok_com_config.grok_ws_url;
    let mut lock = LeaderLock::new(ws_url);
    let socket_path = lock.socket_path().clone();
    match lock.try_acquire() {
        Ok(true) => {
            lock.write_pid()?;
            debug!("Acquired leader lock, proceeding as leader");
        }
        Ok(false) => {
            if crate::leader::listener_is_ready(&socket_path) {
                info!(
                    "Another process holds the leader lock with a bound socket ({}). \
                     Exiting so the client adopts it.",
                    socket_path.display()
                );
                return Err(anyhow::anyhow!(
                    "Another leader already holds the lock at {}",
                    socket_path.display()
                ));
            }
            match lock.acquire_reopen_timeout(LEADER_ACQUIRE_TIMEOUT).await {
                Ok(()) => {
                    lock.write_pid()?;
                    debug!("Acquired leader lock after bounded wait, proceeding as leader");
                }
                Err(LockError::Timeout(_)) => {
                    info!(
                        "Timed out waiting for the leader lock ({}). Exiting so the \
                         client adopts whoever won it.",
                        socket_path.display()
                    );
                    return Err(anyhow::anyhow!(
                        "Timed out acquiring leader lock at {}",
                        socket_path.display()

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Do nothing to fix — exit gracefully; the running leader is healthy and the client will adopt it.
  2. If you genuinely need a second independent agent, change the socket/lock path (e.g. a different XDG_RUNTIME_DIR or profile) so each instance has its own socket_path.
  3. If you believe no other agent is running, verify with `ss -xl | grep <socket-name>` or `lsof <socket_path>` to find the process holding the socket, then stop it.
  4. Remove a stale-but-live socket only after confirming the owner process is defunct.

Example fix

// before: treating second launch as a crash
run_agent_command(...).await?;

// after: treat this specific error as a graceful exit
if let Err(e) = run_agent_command(...).await {
    if e.to_string().starts_with("Another leader already holds the lock") {
        info!("leader already running; exiting so client adopts it");
        return Ok(());
    }
    return Err(e);
}
Defensive patterns

Strategy: fallback

Validate before calling

let socket_path = agent_socket_path();
if crate::leader::listener_is_ready(&socket_path) {
    info!("leader already running at {}", socket_path.display());
    return Ok(ExitCode::from(0)); // adopt existing leader
}

Type guard

fn is_already_leader_err(e: &anyhow::Error) -> bool {
    e.to_string().starts_with("Another leader already holds the lock")
}

Try / catch

match run_agent_command(...).await {
    Err(e) if is_already_leader_err(&e) => Ok(()), // expected: adopt existing leader
    other => other,
}

Prevention

When it happens

Trigger: Calling run_leader (via run_agent_command) when the socket_path already has a live listener bound by another agent process; specifically the check `crate::leader::listener_is_ready(&socket_path)` returns true before lock.acquire_reopen_timeout is attempted.

Common situations: Launching the agent twice (double shell startup, autostart entry plus manual run); a previous leader is still running normally; running an agent in multiple terminal tabs against the same XDG runtime dir.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/14007fefbf261513. Report an issue: GitHub.