Hmbown/CodeWhale · error
Invalid coordination ledger
Error message
Invalid coordination ledger: {error} What it means
After deserializing a persisted sub-agent state snapshot, the coordination ledger inside it is validated with validate_replay() to ensure the recorded events form a consistent, replayable history. If validation fails, the snapshot's coordination data is corrupt or internally inconsistent, so loading is aborted with the validator's error attached.
Solutions
- Restore the state file from backup (or let Codewhale rebuild it by removing the corrupt state under state_root).
- Read the embedded {error} detail to see which ledger invariant failed; if a single entry is corrupt, that snapshot cannot be partially loaded.
- Re-run the workflow that produced the snapshot; live agents will be re-spawned.
- Check disk health if corruption recurs across snapshots.
Example fix
// before: loading a corrupt snapshot
let state = load_subagent_state(path)?;
// after: fall back to a fresh session when the ledger is unrecoverable
let state = match load_subagent_state(path) {
Ok(s) => s,
Err(e) if e.to_string().contains("Invalid coordination ledger") => fresh_state(),
Err(e) => return Err(e),
}; Defensive patterns
Strategy: fallback
Validate before calling
fn ledger_valid(raw: &str) -> bool {
serde_json::from_str::<PersistedSubAgentState>(raw).ok()
.map(|s| s.coordination.validate_replay().is_ok())
.unwrap_or(false)
} Try / catch
let state = match load_subagent_state(path) {
Ok(s) => s,
Err(e) if e.to_string().contains("Invalid coordination ledger") => {
warn!("corrupt ledger, rebuilding");
backup_and_rebuild(path)
}
Err(e) => return Err(e),
}; Prevention
- Avoid killing the process during state persists (use graceful shutdown).
- Never hand-edit persisted state JSON.
- Take periodic backups of the state directory; check disk health if corruption repeats.
When it happens
Trigger: Restoring sub-agent state from a state file whose coordination entries are missing events, out of order, reference unknown agents, or were truncated by a crash mid-write.
Common situations: Power loss or kill -9 during a state persist; manual edits to the state JSON; copying an inconsistent state file between machines; disk corruption.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid pet score checkpoint.
- Invalid pet score checkpoint.
- Invalid pet state.
- Invalid pet world checkpoint.
- Runtime Chat binding state contains duplicate thread…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9a6619194e92bba5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/mod.rs:4675
legacy
} else {
return Ok(());
}
};
let raw = read_subagent_state_file(&self.state_root, &path)?;
let state = serde_json::from_str::<PersistedSubAgentState>(&raw)?;
if state.schema_version != SUBAGENT_STATE_SCHEMA_VERSION {
return Err(anyhow!(
"Unsupported sub-agent state schema {}",
state.schema_version
));
}
let mut coordination = state.coordination;
coordination
.validate_replay()
.map_err(|error| anyhow!("Invalid coordination ledger: {error}"))?;
self.agents.clear();
self.worker_records.clear();
self.persist_sequence.store(
state.snapshot_sequence,
std::sync::atomic::Ordering::Relaxed,
);
self.coordination = coordination;
self.resume_targets = state.resume_targets;
for persisted in state.agents {
let nickname = persisted
.nickname
.filter(|name| generated_whale_name_base(&persisted.id, name).is_none());
let mut status = persisted.status;
if matches!(status, SubAgentStatus::Running) {
status = SubAgentStatus::Interrupted(SUBAGENT_RESTART_REASON.to_string());
}
let started_at = instant_from_duration(Duration::from_millis(persisted.duration_ms));View on GitHub (pinned to 73e0f67d83)