Hmbown/CodeWhale · error · anyhow::Error

Automation admission execution ownership is unverified or…

Error message

Automation admission execution ownership is unverified or belongs to another Runtime

What it means

After the task store matches, dispatch_bound_task checks that the dispatch's execution_scope equals the SharedTaskManager's execution_scope(). This proves the dispatch was claimed by (and its task is owned by) the current Runtime. A missing or mismatched scope means ownership is unverified or the dispatch belongs to another Runtime, so executing it here could run a task owned elsewhere.

Solutions

  1. Replay the dispatch inside the Runtime whose execution_scope matches dispatch.execution_scope.
  2. If this Runtime should own it, re-claim/re-admit the automation in this Runtime so a fresh dispatch with the correct scope is created.
  3. Regenerate or migrate the dispatch record so execution_scope is populated with tasks.execution_scope().
Defensive patterns

Strategy: validation

Validate before calling

if dispatch.execution_scope.as_deref() != Some(tasks.execution_scope()) {
    // not owned by this Runtime; re-admit instead of replaying
}

Try / catch

if let Err(e) = dispatch_bound_task(&mut dispatch, task_id, &tasks).await {
    if e.to_string().contains("execution ownership") {
        re_admit_in_current_runtime(&tasks).await?;
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: dispatch_bound_task called when dispatch.execution_scope is None, or differs from the string returned by tasks.execution_scope() — e.g. a dispatch persisted by Runtime A being replayed inside Runtime B, or a hand-built dispatch without a scope set.

Common situations: Running multiple Runtime instances (dev + prod) sharing one data dir; replaying serialized dispatches across sessions; older persisted automation records written before execution_scope existed.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/automation_manager.rs:2119

    });
    Ok(())
}

fn check_dispatch_store(dispatch: &AutomationDispatch, tasks: &SharedTaskManager) -> Result<()> {
    if tasks.data_dir().canonicalize()? != dispatch.task_data_dir.canonicalize()? {
        bail!("Automation admission belongs to a different task store; it cannot be replayed here");
    }
    Ok(())
}

async fn dispatch_bound_task(
    dispatch: &mut AutomationDispatch,
    task_id: &str,
    tasks: &SharedTaskManager,
) -> Result<crate::task_manager::TaskRecord> {
    check_dispatch_store(dispatch, tasks)?;
    if dispatch.execution_scope.as_deref() != Some(tasks.execution_scope()) {
        bail!(
            "Automation admission execution ownership is unverified or belongs to another Runtime"
        );
    }
    let task = if dispatch.accepted {
        tasks
            .read_bound_task(task_id)?
            .context("Accepted automation task is missing; refusing to replay it")?
    } else {
        tasks
            .recover_task_admission(dispatch.request.clone(), task_id.to_owned())
            .await?
    };
    crate::task_manager::validate_bound_task_request(&task, &dispatch.request)?;
    dispatch.accepted = true;
    dispatch.suppress_report = dispatch.delivery_mode == AutomationDeliveryMode::Watcher
        && task.status == TaskStatus::Completed
        && task
            .result_summary

View on GitHub (pinned to 73e0f67d83)