Hmbown/CodeWhale · error

Bound task identity or schema does not match its durable…

Error message

Bound task identity or schema does not match its durable admission

What it means

When reading a durable bound-task file, the decoded TaskRecord must have the same id as the file's bound task id and a schema_version not newer than the current supported version. Otherwise the durable admission cannot be matched to the request, so the read fails rather than trusting a mismatched record.

Solutions

  1. Upgrade to the newer app version whose CURRENT_TASK_SCHEMA_VERSION covers the file
  2. Correct the task_id argument to match the record actually stored in the file
  3. Fix or remove the mis-named task file so identity matches its durable location

Example fix

// before: reading with mismatched id
let t = manager.read_bound_task("task_0000000000000000")?;
// after: match id to file content
let t = manager.read_bound_task(&stored_task_id)?; // stored_task_id == record.id
Defensive patterns

Strategy: validation

Validate before calling

let record: TaskRecord = serde_json::from_slice(&bytes)?;
if record.id != requested_id { return Err(anyhow!("id mismatch with durable file")); }
if record.schema_version > CURRENT_TASK_SCHEMA_VERSION { return Err(anyhow!("schema too new")); }

Type guard

fn bound_record_matches(bytes: &[u8], task_id: &str, supported: u32) -> Option<TaskRecord> {
    let t: TaskRecord = serde_json::from_slice(bytes).ok()?;
    (t.id == task_id && t.schema_version <= supported).then_some(t)
}

Try / catch

match manager.read_bound_task(id).await {
    Err(e) if e.to_string().contains("identity or schema does not match") => {
        // try newer app version, or locate the correctly named file
        eprintln!("bound record unusable for {id}: {e}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling read_bound_task_file (directly or via recovery/admission) when the JSON record's `id` differs from the requested task_id, or its schema_version exceeds CURRENT_TASK_SCHEMA_VERSION.

Common situations: A task file was renamed or copied under the wrong id; a newer app version wrote the file and an older version reads it (forward-compatibility gap); a client passed a task_id that doesn't match the stored record.

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


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/f63a67d900b57fa8. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/task_manager.rs:3097

fn validate_preallocated_task_id(task_id: &str) -> Result<()> {
    if task_id.len() != 21
        || !task_id.starts_with("task_")
        || !task_id[5..].chars().all(|ch| ch.is_ascii_hexdigit())
    {
        bail!("Invalid preallocated task id: expected task_<16hex>");
    }
    Ok(())
}

fn read_bound_task_file(path: &Path, task_id: &str) -> Result<Option<TaskRecord>> {
    let bytes = match fs::read(path) {
        Ok(bytes) => bytes,
        Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None),
        Err(error) => return Err(error).context("read bound task"),
    };
    let task: TaskRecord = serde_json::from_slice(&bytes).context("decode bound task")?;
    if task.id != task_id || task.schema_version > CURRENT_TASK_SCHEMA_VERSION {
        bail!("Bound task identity or schema does not match its durable admission");
    }
    Ok(Some(task))
}

pub(crate) fn validate_bound_task_request(
    task: &TaskRecord,
    request: &NewTaskRequest,
) -> Result<()> {
    if task.prompt != request.prompt.trim()
        || task.owner_session_id != request.owner_session_id
        || task.model_provider != request.model_provider
        || task.model_provider_id != request.model_provider_id
        || request
            .model
            .as_ref()
            .is_some_and(|value| value != &task.model)
        || request
            .workspace

View on GitHub (pinned to 73e0f67d83)