{"record":{"id":"79ee0f11c1076544","repo":"Hmbown/CodeWhale","slug":"this-runtime-already-owns-a-task-execution-manager","errorCode":null,"errorMessage":"This Runtime already owns a task execution manager","messagePattern":"This Runtime already owns a task execution manager","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":5269,"sourceCode":"        monitors.push(retained_completion(worker));\n    }\n\n    fn ensure_accepting_execution(&self) -> Result<()> {\n        if self.cancel_token.is_cancelled() {\n            bail!(\"Runtime is shutting down; execution admission is closed\");\n        }\n        Ok(())\n    }\n\n    /// Runtime clones retained by live Engine/tool work retain this lease too.\n    /// A TaskManager cancellation timeout cannot release execution ownership.\n    pub(crate) fn retain_task_execution_lease(\n        &self,\n        lease: Arc<crate::task_manager::TaskExecutionLease>,\n    ) -> Result<()> {\n        let mut current = self.task_execution_lease.lock();\n        if current.is_some() {\n            bail!(\"This Runtime already owns a task execution manager\");\n        }\n        *current = Some(lease);\n        Ok(())\n    }\n\n    /// Attach the automation manager for model-visible scheduling tools.\n    pub fn attach_automation_manager(\n        &self,\n        automations: crate::automation_manager::SharedAutomationManager,\n    ) {\n        *self.automations.lock() = Some(automations);\n    }\n\n    /// Mints an approval identifier that no provider can predict or collide\n    /// with. Every `approval_id` an external client ever sees comes from here,\n    /// so `approval_id` never carries a provider tool-call ID and a client can\n    /// echo it without inspecting where it came from.\n    fn mint_approval_id() -> String {","sourceCodeStart":5251,"sourceCodeEnd":5287,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_threads.rs#L5251-L5287","documentation":"retain_task_execution_lease stores the single TaskExecutionLease on the Runtime and bails if one is already present. The Runtime may own at most one task execution manager, so a second retain would silently overwrite or corrupt execution ownership.","triggerScenarios":"Calling retain_task_execution_lease twice on the same Runtime instance (double initialization, or re-attaching a new TaskManager without detaching the old lease).","commonSituations":"Re-running an init/setup path; a plugin or automation layer attaching its own TaskManager on top of the engine's; accidental duplicate bootstrap during startup retries.","solutions":["Ensure retain_task_execution_lease is called only once per Runtime lifetime","Reuse the existing lease instead of attaching a new one","Create a fresh Runtime if you genuinely need a new task execution manager"],"exampleFix":"// before\nruntime.retain_task_execution_lease(lease_a)?;\nruntime.retain_task_execution_lease(lease_b)?; // bails\n// after\nruntime.retain_task_execution_lease(lease_a)?;\nlet lease = runtime.task_execution_lease(); // reuse existing","handlingStrategy":"validation","validationCode":"// attach once, at construction\nonce: OnceCell<TaskExecutionLease>","typeGuard":null,"tryCatchPattern":"match runtime.retain_task_execution_lease(lease) {\n    Err(e) if e.to_string().contains(\"already owns a task execution manager\") => {\n        // reuse the existing lease instead\n    }\n    other => other?,\n}","preventionTips":["Initialize the task execution manager exactly once, at Runtime construction","Idempotence-guard your bootstrap path (OnceCell/OnceLock)","Never attach a second TaskManager to a live Runtime"],"tags":["lifecycle","state","invariant"],"backgroundTag":"invalid-state-transition","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}