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
- Check the wrapped {error} — typically the acquisition thread died or timed out; fix that panic/timeout first
- Retry the coordination acquisition after a short delay
- Inspect the helper thread for panics (unwrap on lock/file ops) and make it propagate errors instead
- 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
- Make the acquisition thread propagate errors instead of panicking/dropping the channel
- Keep helper-thread lifetimes tied to the request so release_tx cannot drop early
- Use bounded retries with backoff for lock acquisition
- Log thread panics with a panic hook so failures are diagnosable
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- another Codewhale process
- for
- Another pet recorder is using this output.
- Automation lock must be a regular file
- Automation lock must not have hard links
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)