Hmbown/CodeWhale · error
for
Error message
{COORDINATION_LOCK_TIMEOUT_MARKER} for {}: {error} What it means
The delegated coordination acquisition runs the locking attempt on a worker thread with a timeout signaled via a channel (release_tx). If the worker errors out or the wait times out (receiver gets Err), the library joins the thread and throws this marker error naming the state_root and the underlying error, telling the caller the coordination lock could not be acquired in time.
Solutions
- Retry after the competing process finishes; the underlying error text names the real cause.
- Increase patience: close other Codewhale sessions using the same state_root before retrying.
- Check filesystem permissions on state_root (the worker may be failing to open/create the lock file).
- If the holder is dead, clear the stale lock file and retry.
Example fix
// before: immediate acquisition attempt under contention let handle = acquire_delegated(state_root)?; // after: wait for prior holder to release, with backoff wait_for_coordination_release(state_root, Duration::from_secs(30)); let handle = acquire_delegated(state_root)?;
Defensive patterns
Strategy: retry
Validate before calling
// probe lock availability with a short-lived attempt before the real call
fn coordination_available(state_root: &Path) -> bool {
try_acquire_coordination_with_timeout(state_root, Duration::from_millis(100)).is_ok()
} Try / catch
match acquire_delegated_coordination(state_root) {
Err(e) if e.to_string().contains("lock timeout") || e.to_string().contains("LOCK_TIMEOUT") => {
tokio::time::sleep(Duration::from_secs(5)).await;
acquire_delegated_coordination(state_root)
}
r => r,
} Prevention
- Close competing Codewhale sessions sharing the same state_root before launching delegated work.
- Apply exponential backoff on retries instead of hammering the lock.
- Verify filesystem permissions on the state directory so worker threads do not fail on IO.
When it happens
Trigger: Invoking a delegated sub-agent operation while another process holds the coordination lock past the acquisition timeout, or the worker thread itself returned an error (permission problem, IO failure on the lock file).
Common situations: Long-running agent session in another window holding coordination; a hung/stuck worker thread; disk or permission errors on the state directory under load.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Task store is busy; state is unavailable
- another Codewhale process
- Another pet recorder is using this output.
- child wall-time budget exhausted
- for
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ba07c6671a1e017f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:3473
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 73e0f67d83)