Hmbown/CodeWhale · error
Fleet task has an invalid durable member snapshot
Error message
Fleet task {} has an invalid durable member snapshot: {error} What it means
Thrown by resolve_task_agent_profile when a Fleet task's metadata contains a durable frozen-member snapshot under FROZEN_FLEET_MEMBER_METADATA_KEY, but the stored serde_json::Value cannot deserialize into FrozenFleetMember. Because this snapshot is the durable record of which profile a worker uses, an invalid snapshot is refused rather than silently ignored, keeping frozen membership stable across roster edits.
Solutions
- Fix or regenerate the snapshot: re-freeze the task (re-run the freeze path) so metadata is rewritten from a valid roster.
- Delete the FROZEN_FLEET_MEMBER_METADATA_KEY entry and set worker.agent_profile explicitly so resolution falls back to selector-based lookup.
- Restore the task/ledger record from backup if it was corrupted.
- If snapshots come from an older version, migrate or drop them before running the new validator.
Example fix
// before: hand-edited metadata
{"frozen_member": {"profile": "reviewer"}}
// after: remove and let freeze rewrite it
{} // then set worker.agent_profile = "reviewer" Defensive patterns
Strategy: validation
Validate before calling
// Rust
if let Some(v) = task_spec.metadata.get(FROZEN_FLEET_MEMBER_METADATA_KEY) {
if let Err(e) = serde_json::from_value::<FrozenFleetMember>(v.clone()) {
eprintln!("corrupt snapshot on task {}: {e}", task_spec.id);
}
} Try / catch
// Rust
match resolve_task_agent_profile(&task_spec, &profiles) {
Err(e) if e.to_string().contains("invalid durable member snapshot") => {
log::warn!("task {} needs re-freeze", task_spec.id);
}
other => other?,
} Prevention
- Never hand-edit task metadata JSON; re-freeze through the tool instead.
- After a version upgrade, run the validators once to surface snapshot schema drift.
- Back up ledger/task storage before edits so snapshots can be restored.
When it happens
Trigger: Resolving a task's agent profile (via validate_task_agent_profiles, fleet_task_to_worker_spec_with_profiles, resolve_fleet_route_*) when its metadata JSON was hand-edited, written by an older/other version with a different snapshot schema, or corrupted in the ledger.
Common situations: Manual metadata edits in the ledger/task store; schema change between Codewhale versions so old snapshots no longer match FrozenFleetMember; partial JSON write during a crash.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- deserialize
- roundtrip
- <serde_json deserialization error>
- (serde_json deserialization error wrapped as…
- (serde_json deserialization error wrapped as…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/9634da7e77a64e2b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/fleet/worker_runtime.rs:978
provider: Option<&str>,
) -> bool {
let requested = requested.trim();
let model = model.trim();
requested == model
|| provider
.and_then(non_empty_trimmed)
.and_then(|provider| requested.strip_prefix(&format!("{provider}/")))
.is_some_and(|requested_model| requested_model == model)
}
fn resolve_task_agent_profile<'a>(
task_spec: &FleetTaskSpec,
agent_profiles: &'a [AgentProfile],
) -> Result<Option<Cow<'a, AgentProfile>>> {
if let Some(snapshot) = task_spec.metadata.get(FROZEN_FLEET_MEMBER_METADATA_KEY) {
let snapshot: FrozenFleetMember =
serde_json::from_value(snapshot.clone()).map_err(|error| {
anyhow::anyhow!(
"Fleet task {} has an invalid durable member snapshot: {error}",
task_spec.id
)
})?;
return Ok(Some(Cow::Owned(snapshot.into_profile()?)));
}
let Some(worker) = task_spec.worker.as_ref() else {
return Ok(None);
};
if let Some(selector) = worker
.agent_profile
.as_deref()
.map(str::trim)
.filter(|selector| !selector.is_empty())
{
let profile = resolve_member_in_profiles(agent_profiles, selector).map_err(|error| {
anyhow::anyhow!(
"Fleet task {} has invalid worker.agent_profile selector {selector:?}: {error}",View on GitHub (pinned to 73e0f67d83)