Hmbown/CodeWhale · error

Task generation has no execution scope

Error message

Task generation has no execution scope

What it means

When loading persisted tasks, each task may carry an execution_generation (an opaque execution/run identifier). A generation is only meaningful relative to its execution_scope, so deserialization rejects any task record that has a generation but no scope. This is a persisted-state invariant check in the task manager's load path.

Solutions

  1. Open the task state file at the storage location and either remove the execution_generation field or add a matching execution_scope.
  2. If caused by a version migration, restore the task file from before the upgrade or re-create the task.
  3. Check for tools/scripts that write task records partially and fix them to always emit scope together with generation.

Example fix

// before (task state file)
{"id": "a1b2", "execution_generation": "gen-7"}
// after
{"id": "a1b2", "execution_scope": "session-1", "execution_generation": "gen-7"}
Defensive patterns

Strategy: validation

Validate before calling

if (task.execution_generation != null && task.execution_scope == null) { throw new Error("task record has generation without scope"); }

Type guard

function hasConsistentExecution(t) { return t.execution_generation == null || t.execution_scope != null; }

Prevention

When it happens

Trigger: Loading tasks from disk/storage where a task's JSON record contains execution_generation set but execution_scope null/absent — e.g. a hand-edited or older/partially-written task file.

Common situations: Upgrading from an older schema where generation existed before scope was introduced; manually editing or merging task state files; a serialization bug writing generation without scope.

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/96ecddbf2acb707a. Report an issue: GitHub.

Appendix: source

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

                .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
                );
            }
            ensure_safe_storage_id("task id", &task.id)?;
            if path.file_stem().and_then(|stem| stem.to_str()) != Some(task.id.as_str()) {
                bail!("Task record identity differs from its path");
            }
            if let Some(scope) = &task.execution_scope {
                validate_execution_id(scope, 64)?;
            }
            if let Some(generation) = &task.execution_generation {
                validate_execution_id(generation, 32)?;
                if task.execution_scope.is_none() {
                    bail!("Task generation has no execution scope");
                }
            }
            tasks.insert(task.id.clone(), task);
        }
    }

    let mut queue = if queue_path.exists() {
        let content = fs::read_to_string(queue_path)
            .with_context(|| format!("Failed to read queue file {}", queue_path.display()))?;
        let parsed: QueueFile = serde_json::from_str(&content)
            .with_context(|| format!("Failed to parse queue file {}", queue_path.display()))?;
        VecDeque::from(parsed.queue)
    } else {
        VecDeque::new()
    };

    queue.retain(|id| {
        tasks

View on GitHub (pinned to 73e0f67d83)