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

  1. Fix or regenerate the snapshot: re-freeze the task (re-run the freeze path) so metadata is rewritten from a valid roster.
  2. Delete the FROZEN_FLEET_MEMBER_METADATA_KEY entry and set worker.agent_profile explicitly so resolution falls back to selector-based lookup.
  3. Restore the task/ledger record from backup if it was corrupted.
  4. 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

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


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)