Hmbown/CodeWhale · error
Task execution scope is unverified or belongs to another…
Error message
Task execution scope is unverified or belongs to another Runtime; refusing adoption
What it means
During admission, a task record's execution_scope must exactly match the current Runtime's execution_scope(). A record whose scope is missing (unverified) or belongs to another Runtime is refused for adoption, preventing a worker from executing tasks created under a different execution identity (different lease namespace/generation).
Solutions
- Only adopt task records produced by the same Runtime/scope; verify task.execution_scope equals the current execution_scope() before admission
- Delete or archive durable task files from foreign scopes so recovery does not attempt to adopt them
- If scopes legitimately changed across an upgrade, run the migration that re-stamps records with the new scope
- Set execution_scope explicitly when constructing TaskRecord; never admit records with a None scope
Example fix
// before
mgr.adopt_task(record).await?; // record.execution_scope = Some("old-scope")
// after
if record.execution_scope.as_deref() == Some(mgr.execution_scope()) {
mgr.adopt_task(record).await?;
} else {
archive_foreign_task(&record)?;
} Defensive patterns
Strategy: validation
Validate before calling
anyhow::ensure!(task.execution_scope.as_deref() == Some(mgr.execution_scope()), "task belongs to another runtime scope");
Try / catch
match adopt_result { Err(e) if e.to_string().contains("execution scope") => archive_foreign_record(&task), r => r?, } Prevention
- Never copy task stores between profiles/machines without re-stamping scope
- Always populate execution_scope on newly built TaskRecords
- Run scope migrations on upgrade before recovery replay
When it happens
Trigger: Calling admit_task_record (via recovery, adoption, or add paths) with a TaskRecord whose execution_scope is None or whose stored scope string differs from self.execution_scope() — e.g. a task file copied from another profile/machine or created before a scope regeneration.
Common situations: Copying a tasks directory between machines or profiles; runtime scope regenerating after an id-format change (related to validate_execution_id); loading old durable records from a previous version that stored no scope.
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
- A pinned task provider requires an explicit model
- Invalid task execution identity
- Task manager is shutting down; admission is closed
- Task prompt cannot be empty
- Unpromoted task stage contains execution evidence; refusing…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1cf56fc434418241.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/task_manager.rs:1774
kind: "queued".to_string(),
summary: "Task queued".to_string(),
detail_path: None,
}],
};
self.admit_task_record(task, false).await
}
async fn admit_task_record(&self, task: TaskRecord, recover_stage: bool) -> Result<TaskRecord> {
{
let mut state = self.state.lock().await;
let _transaction = self.lock_store().await?;
self.refresh_locked(&mut state)?;
if self.cancel_token.is_cancelled() {
bail!("Task manager is shutting down; admission is closed");
}
if task.execution_scope.as_deref() != Some(self.execution_scope()) {
bail!(
"Task execution scope is unverified or belongs to another Runtime; refusing adoption"
);
}
let task_path = self.tasks_dir.join(format!("{}.json", task.id));
// The staged extension is intentionally not `.json`, so startup
// replay ignores an interrupted create until the queue write has
// succeeded and this file is atomically promoted.
let staged_task_path = self.tasks_dir.join(format!(".{}.json.pending", task.id));
if recover_stage {
if let Some(accepted) = self.read_bound_task(&task.id)? {
validate_bound_task_request(&accepted, &NewTaskRequest::from_task(&task))?;
return Ok(accepted);
}
let current = read_bound_task_file(&staged_task_path, &task.id)?
.context("Unaccepted task stage disappeared during recovery")?;
if serde_json::to_value(¤t)? != serde_json::to_value(&task)? {
bail!("Unaccepted task stage changed during recovery");
}View on GitHub (pinned to 73e0f67d83)