Hmbown/CodeWhale · error · anyhow::Error

Task schema v{} is newer than supported v{}

Error message

Task schema v{} is newer than supported v{}

What it means

Forward-compatibility guard while loading the persisted task store at boot: a task JSON file declares a schema_version greater than CURRENT_TASK_SCHEMA_VERSION, so this build cannot safely interpret it. Older files (schema_version <= current) load normally; newer ones abort the load.

Source

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

fn load_state(tasks_dir: &Path, queue_path: &Path) -> Result<LoadedTaskState> {
    let mut tasks = HashMap::new();
    let mut recovered = Vec::new();
    if tasks_dir.exists() {
        for entry in fs::read_dir(tasks_dir)
            .with_context(|| format!("Failed to read tasks dir {}", tasks_dir.display()))?
        {
            let entry = entry?;
            let path = entry.path();
            if path.extension().is_none_or(|ext| ext != "json") {
                continue;
            }
            let content = fs::read_to_string(&path)
                .with_context(|| format!("Failed to read task file {}", path.display()))?;
            let mut task: TaskRecord = serde_json::from_str(&content)
                .with_context(|| format!("Failed to parse task file {}", path.display()))?;
            if task.schema_version > CURRENT_TASK_SCHEMA_VERSION {
                bail!(
                    "Task schema v{} is newer than supported v{}",
                    task.schema_version,
                    CURRENT_TASK_SCHEMA_VERSION
                );
            }
            if task.status == TaskStatus::Running {
                let now = Utc::now();
                let duration_ms = task.started_at.and_then(|started| {
                    u64::try_from(now.signed_duration_since(started).num_milliseconds()).ok()
                });
                task.status = TaskStatus::Failed;
                task.lifecycle_seq = task.lifecycle_seq.saturating_add(1);
                task.ended_at = Some(now);
                task.duration_ms = duration_ms;
                task.terminal_reason = Some(TaskTerminalReason::Failed.as_str().to_string());
                task.error = Some(
                    "Interrupted by process restart; prior process is not attached".to_string(),
                );

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Run the newer Codewhale version that wrote the files (its schema is a superset) instead of the downgraded binary.
  2. If the downgraded version must be used, move the tasks dir aside (e.g. mv tasks tasks.from-v2) so a fresh store is created, and keep the old dir for the newer version to read later.
  3. Never hand-edit schema_version downward in task files; fields you cannot parse may be load-bearing for the newer version.
Defensive patterns

Strategy: validation

Validate before calling

fn store_is_backward_compatible(tasks_dir: &Path) -> Result<()> {
    for entry in fs::read_dir(tasks_dir)? {
        let path = entry?.path();
        if path.extension().is_none_or(|e| e != "json") { continue; }
        let v: serde_json::Value = serde_json::from_str(&fs::read_to_string(&path)?)?;
        if v["schema_version"].as_u64().unwrap_or(0) > CURRENT_TASK_SCHEMA_VERSION as u64 {
            bail!("newer store in {} ({})", path.display(), v["schema_version"]);
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: Opening a tasks directory that was last written by a newer Codewhale release, then running an older binary against it; downgrading after trying a pre-release; a shared state dir used by two versions.

Common situations: Version rollback after an upgrade; CI or containers pinned to an older image while a newer tool wrote the state; copying a tasks dir between machines with different versions.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/66b0a38fc93567e8. Report an issue: GitHub.