Hmbown/CodeWhale · error · anyhow::Error

for

Error message

{COORDINATION_LOCK_TIMEOUT_MARKER} for {}: {error}

What it means

Acquiring delegated coordination runs in a helper thread with a timeout; the requester waits on a release channel. If the wait itself errors (e.g. the channel drops or the wait future fails before the lock is acquired), the thread is joined and this COORDINATION_LOCK_TIMEOUT_MARKER error is returned with the state root and underlying error.

Solutions

  1. Check the wrapped {error} — typically the acquisition thread died or timed out; fix that panic/timeout first
  2. Retry the coordination acquisition after a short delay
  3. Inspect the helper thread for panics (unwrap on lock/file ops) and make it propagate errors instead
  4. If another process holds the lock long-term, wait for it to exit rather than retrying immediately
Defensive patterns

Strategy: retry

Try / catch

match coordination_wait_rx.await {
    Ok(Ok(guard)) => guard,
    Ok(Err(e)) | Err(_) => {
        // sender dropped or wait failed: back off and retry acquisition once
        tokio::time::sleep(Duration::from_millis(200)).await;
        return retry_coordination_acquire(state_root);
    }
}

Prevention

When it happens

Trigger: The oneshot/signal wait for coordination-lock acquisition fails (sender dropped without sending, or wait error) while trying to take the coordination lock for state_root.

Common situations: The lock-acquisition thread panicked or exited early, dropping release_tx; a timeout racing a lock that never becomes free; scheduling starvation of the helper thread.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/ba07c6671a1e017f. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/subagent/mod.rs:3278

                if holder_pid == Some(std::process::id()) {
                    Err(anyhow!(
                        "{COORDINATION_SAME_PROCESS_HANDOVER} for {}: {error}",
                        state_root.display()
                    ))
                } else {
                    Err(anyhow!(
                        "another Codewhale process{} owns delegated coordination for {}: {error}",
                        holder_pid
                            .map(|pid| format!(" (pid {pid})"))
                            .unwrap_or_default(),
                        state_root.display()
                    ))
                }
            }
            Err(error) => {
                drop(release_tx);
                let _ = thread.join();
                Err(anyhow!(
                    "{COORDINATION_LOCK_TIMEOUT_MARKER} for {}: {error}",
                    state_root.display()
                ))
            }
        }
    }
}

impl Drop for CoordinationProcessLock {
    fn drop(&mut self) {
        self.release.take();
        if let Some(thread) = self.thread.take() {
            let _ = thread.join();
        }
    }
}

pub struct SubAgentManager {

View on GitHub (pinned to 433685b202)