Hmbown/CodeWhale · error
Automation admission belongs to a different task store; it…
Error message
Automation admission belongs to a different task store; it cannot be replayed here
What it means
Before replaying an admitted automation dispatch, the library verifies that the dispatch's recorded task_data_dir matches the current SharedTaskManager's data directory (compared via canonicalize). If they differ, the admission was created against a different task store and cannot be replayed here; executing it would bind the task into the wrong store. The error makes store mismatch an explicit failure instead of silently running an automation in the wrong context.
Solutions
- Replay the dispatch against the task manager whose data_dir matches dispatch.task_data_dir
- Re-admit the automation in the current store (create a fresh dispatch) instead of replaying the foreign one
- Point the task manager at the original data directory (restore the expected path) if the record is the one you want
- If migrating stores deliberately, rewrite dispatch.task_data_dir to the new canonical path via a migration, not at dispatch time
Example fix
// before
dispatch_bound_task(&mut dispatch, &task_id, &wrong_store_tasks).await?;
// after
if tasks.data_dir().canonicalize()? == dispatch.task_data_dir.canonicalize()? {
dispatch_bound_task(&mut dispatch, &task_id, &tasks).await?;
} else {
// re-admit in this store or route to the owning store
} Defensive patterns
Strategy: validation
Validate before calling
if tasks.data_dir().canonicalize()? != dispatch.task_data_dir.canonicalize()? {
return Err(anyhow!("dispatch belongs to a different task store"));
} Try / catch
match dispatch_bound_task(&mut dispatch, &task_id, &tasks).await {
Err(e) if e.to_string().contains("different task store") => {
// route to owning store or re-admit locally
},
other => other?,
} Prevention
- Keep one canonical data directory per environment; don't copy automation state between stores
- When migrating stores, re-admit automations instead of copying dispatch records
- Record the owning store alongside any exported dispatch data
- Canonicalize paths before comparing them yourself
When it happens
Trigger: Calling dispatch_bound_task (which calls check_dispatch_store) with a dispatch whose task_data_dir canonicalizes to a different path than tasks.data_dir() — e.g. dispatching a trigger or run record persisted under another profile/data root.
Common situations: Copying automation state files between machines or between dev and production data directories; changing CODEX_HOME/data dir between runs; running two profiles concurrently and replaying a record from the other profile; restoring backups into a different location.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- approval log has no parent
- Automation admission execution ownership is unverified or…
- Automation execution ownership is unverified
- Automation name is required
- Automation run has no durable task binding
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/ff937b405662da15.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/automation_manager.rs:2091
execution_scope: automation.execution_scope.clone(),
request: automation_task_request(automation),
task_data_dir: task_data_dir
.canonicalize()
.context("resolve task store before automation admission")?,
accepted: false,
delivery_mode: automation.delivery_mode(),
suppress_report: false,
schedule: scheduled.then(|| AdmittedSchedule {
updated_at: automation.updated_at,
rrule: automation.rrule.clone(),
}),
});
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)?View on GitHub (pinned to 433685b202)