{"record":{"id":"fff5dfd8573cd603","repo":"Hmbown/CodeWhale","slug":"runtime-checked","errorCode":null,"errorMessage":"runtime checked","messagePattern":"runtime checked","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/coord.rs","lineNumber":337,"sourceCode":"            .continuation_target_for_caller(\n                &context.state_namespace,\n                agent_ref,\n                self.caller_agent_id.as_deref(),\n                \"agents/followup\",\n            )\n            .map_err(|error| ToolError::invalid_input(error.to_string()))?;\n        let snapshot = manager\n            .get_result(&target)\n            .map_err(|error| ToolError::invalid_input(error.to_string()))?;\n        let resumed_already = source != target;\n        let receipt = if super::subagent_checkpoint_is_continuable(&snapshot)\n            && self.runtime.is_some()\n        {\n            let snapshot = manager\n                .resume_from_checkpoint_for_session(\n                    &context.state_namespace,\n                    Arc::clone(&self.manager),\n                    self.runtime.clone().expect(\"runtime checked\"),\n                    &target,\n                    message,\n                )\n                .map_err(|error| ToolError::execution_failed(error.to_string()))?;\n            ParentMailReceipt {\n                agent_id: snapshot.agent_id.clone(),\n                status: subagent_status_name(&snapshot.status).to_string(),\n                queue_depth: 0,\n                woke: true,\n                continued_from_checkpoint: true,\n                continuation_handle: None,\n                note: format!(\n                    \"resumed from checkpoint {source} as {}; original receipt retained\",\n                    snapshot.agent_id\n                ),\n            }\n        } else if resumed_already && snapshot.status != SubAgentStatus::Running {\n            ParentMailReceipt {","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/subagent/coord.rs#L319-L355","documentation":"In `followup_one` (crates/tui/src/tools/subagent/coord.rs:337), `self.runtime.clone().expect(\"runtime checked\")` unwraps an `Option<Runtime>` after a preceding branch checked `self.runtime.is_some()`. The `expect` asserts the earlier check guarantees presence. A panic means the runtime option was `None` despite the preceding condition — i.e. the guard and the use drifted apart after a refactor.","triggerScenarios":"Invoking the subagent `followup` action's resume-from-checkpoint path when the combined guard (`manager.is_some() && self.runtime.is_some()`) was satisfied, but `self.runtime` became `None` between check and use, or the guard was edited and no longer covers this branch.","commonSituations":"Concurrent mutation of the coordinator's runtime field, or a refactor that weakened the `is_some()` precondition while keeping the `expect` in place.","solutions":["Re-read the guard condition above line 337 and confirm it still implies `self.runtime.is_some()`.","Bind the option once: `if let Some(runtime) = self.runtime.as_ref() { ... }` instead of check-then-expect.","If the runtime can legitimately disappear, return a `ToolError::execution_failed(\"runtime unavailable\")` instead of panicking.","Check for code paths that clear `self.runtime` while a followup is executing."],"exampleFix":"// before\nself.runtime.clone().expect(\"runtime checked\"),\n// after\nmatch self.runtime.clone() {\n    Some(runtime) => /* use runtime */,\n    None => return Err(ToolError::execution_failed(\"runtime unavailable for followup resume\")),\n}","handlingStrategy":"type-guard","validationCode":"// Precondition check the caller can run before invoking followup\nif coordinator.runtime.is_none() {\n    return Err(\"subagent runtime unavailable; cannot resume followup\");\n}","typeGuard":"// Narrow once instead of check-then-expect\nlet Some(runtime) = self.runtime.as_ref() else {\n    return Err(ToolError::execution_failed(\"runtime unavailable\"));\n};","tryCatchPattern":"// Handle the None case explicitly at the call boundary\nmatch self.runtime.clone() {\n    Some(rt) => /* proceed with resume_from_checkpoint_for_session */,\n    None => Err(ToolError::execution_failed(\"runtime unavailable for followup\")),\n}","preventionTips":["Bind Option values with let-else/if-let instead of is_some() followed by expect.","Never clear coordinator runtime state while a followup is in flight.","Add a guard test asserting followup fails gracefully without a runtime.","Keep the guard and the use within one expression so refactors cannot separate them."],"tags":["null-value","invariant","subagent","panic"],"backgroundTag":"null-argument","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}