{"record":{"id":"6890007254c599be","repo":"Hmbown/CodeWhale","slug":"automation-execution-ownership-is-unverified","errorCode":null,"errorMessage":"Automation execution ownership is unverified","messagePattern":"Automation execution ownership is unverified","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/automation_manager.rs","lineNumber":2068,"sourceCode":"        model_provider: automation.model_provider.clone(),\n        model_provider_id: automation.model_provider_id.clone(),\n        workspace: automation.cwds.first().cloned(),\n        mode: Some(automation.task_mode()),\n        allow_shell: Some(automation.task_allow_shell()),\n        trust_mode: Some(automation.task_trust_mode()),\n        auto_approve: Some(automation.task_auto_approve()),\n        owner_session_id: None,\n    }\n}\n\nfn bind_run_dispatch(\n    run: &mut AutomationRunRecord,\n    automation: &AutomationRecord,\n    task_data_dir: &Path,\n    scheduled: bool,\n) -> Result<()> {\n    if automation.execution_scope.is_none() {\n        bail!(\"Automation execution ownership is unverified\");\n    }\n    run.schema_version = CURRENT_RUN_SCHEMA_VERSION;\n    run.task_id = Some(crate::task_manager::TaskManager::new_task_id());\n    run.dispatch = Some(AutomationDispatch {\n        execution_scope: automation.execution_scope.clone(),\n        request: automation_task_request(automation),\n        task_data_dir: task_data_dir\n            .canonicalize()\n            .context(\"resolve task store before automation admission\")?,\n        accepted: false,\n        delivery_mode: automation.delivery_mode(),\n        suppress_report: false,\n        schedule: scheduled.then(|| AdmittedSchedule {\n            updated_at: automation.updated_at,\n            rrule: automation.rrule.clone(),\n        }),\n    });\n    Ok(())","sourceCodeStart":2050,"sourceCodeEnd":2086,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/automation_manager.rs#L2050-L2086","documentation":"This error is thrown when preparing an automation run record for an automation whose execution_scope field is None. The library requires every admitted automation to carry an execution scope that verifies which Runtime/task store owns its execution; a record without one cannot be proven to belong here, so admission is refused rather than guessed. It is a guard against executing automations with unverified ownership.","triggerScenarios":"Calling the run-preparation function with an AutomationRecord loaded from storage (or constructed in code) where automation.execution_scope is None.","commonSituations":"Hand-written or migrated automation JSON files that predate the execution_scope field; records copied between task stores with the scope stripped; tests constructing AutomationRecord fixtures without setting execution_scope; older schema files loaded by a newer build that now requires the field.","solutions":["Set automation.execution_scope to the owning scope before admission (it is normally assigned when the automation is admitted/saved)","Re-admit or re-save the automation through the normal API so execution_scope is populated and persisted","If the record came from an old file, migrate it by assigning the current task store's execution scope and rewriting the file","In tests/fixtures, always populate execution_scope"],"exampleFix":"// before\nlet mut automation: AutomationRecord = serde_json::from_str(&raw)?;\n// admission bails: execution_scope is None\n// after\nlet mut automation: AutomationRecord = serde_json::from_str(&raw)?;\nautomation.execution_scope = Some(tasks.execution_scope().to_string());\nmanager.save_automation(&automation)?;","handlingStrategy":"validation","validationCode":"if automation.execution_scope.is_none() {\n    automation.execution_scope = Some(tasks.execution_scope().to_string());\n}","typeGuard":"fn has_execution_scope(a: &AutomationRecord) -> bool {\n    a.execution_scope.as_deref().map(|s| !s.is_empty()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Always load automations through the library's read/save API so scope is assigned at admission","Migrate old records once, assigning the current store's execution scope","In tests, build fixtures via a constructor that sets execution_scope","Never hand-edit automation JSON to remove scope fields"],"tags":["rust","automation","ownership","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}