{"record":{"id":"b416eb7c6cdfffef","repo":"Hmbown/CodeWhale","slug":"single-target-returned-a-result","errorCode":null,"errorMessage":"single target returned a result","messagePattern":"single target returned a result","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/coord.rs","lineNumber":506,"sourceCode":"                ));\n            }\n            ids\n        };\n        let mut seen = std::collections::HashSet::new();\n        targets.retain(|target| seen.insert(target.clone()));\n        let mut results = Vec::new();\n        let mut errors = Vec::new();\n        // Each mutation and both hierarchy checks share the manager write lock.\n        // A target failure cannot erase successful results from another target.\n        for target in targets {\n            match self.followup_one(&target, message, context).await {\n                Ok(payload) => results.push(payload),\n                Err(error) if single.is_some() => return Err(error),\n                Err(error) => errors.push(json!({\"from\": target, \"error\": error.to_string()})),\n            }\n        }\n        let payload = if single.is_some() {\n            results.pop().expect(\"single target returned a result\")\n        } else {\n            json!({\"action\": \"followup\", \"results\": results, \"errors\": errors})\n        };\n        let mut result = ToolResult::json(&payload)\n            .map_err(|error| ToolError::execution_failed(error.to_string()))?;\n        result.metadata = Some(payload.clone());\n        Ok(result)\n    }\n}\n\n// ── agents/interrupt ─────────────────────────────────────────────────────\n\npub struct AgentsInterruptTool {\n    manager: SharedSubAgentManager,\n    /// Optional caller identity for fail-closed self-interrupt checks.\n    caller_agent_id: Option<String>,\n}\n","sourceCodeStart":488,"sourceCodeEnd":524,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/subagent/coord.rs#L488-L524","documentation":"In `execute` (crates/tui/src/tools/subagent/coord.rs:506), when a single followup target was requested (`single.is_some()`), any error aborts immediately, so the code assumes `results` must contain exactly one payload and calls `results.pop().expect(\"single target returned a result\")`. A panic means the single-target loop pushed nothing to `results` before reaching this line — e.g. the loop body never ran or the success path was skipped.","triggerScenarios":"Executing a `followup` action with exactly one target where `targets` iterated zero times (empty/missing single target entry) while `single` was still `Some`, causing the `pop()` on an empty `results` vec to panic.","commonSituations":"A followup call whose target list deserialized to `Some` but contained an empty or invalid entry that the loop skipped; a refactor that changed how `single` is populated relative to the iteration source.","solutions":["Verify how `single` is derived and ensure it is populated only when the iteration will actually produce one result.","Guard with `results.pop().ok_or_else(|| ToolError::execution_failed(\"single target produced no result\"))?` instead of `expect`.","Add a test for followup with a single target that yields no loop iteration.","Check whether the loop's `continue` paths can skip the single target entirely."],"exampleFix":"// before\nresults.pop().expect(\"single target returned a result\")\n// after\nresults.pop().ok_or_else(|| ToolError::execution_failed(\"single target returned no result\"))?","handlingStrategy":"validation","validationCode":"// Validate target list before dispatch\nif targets.is_empty() {\n    return Err(ToolError::execution_failed(\"followup requires at least one target\"));\n}","typeGuard":"fn single_result(results: Vec<serde_json::Value>) -> Option<serde_json::Value> {\n    if results.len() == 1 { results.into_iter().next() } else { None }\n}","tryCatchPattern":"// Fallible pop instead of expect\nlet payload = results.pop()\n    .ok_or_else(|| ToolError::execution_failed(\"single target returned no result\"))?;","preventionTips":["Derive `single` from the same collection the loop iterates so they cannot disagree.","Return an execution error for empty or skipped targets instead of panicking.","Test followup with zero targets, one target, and multiple targets.","Avoid expect on collection pops at API boundaries."],"tags":["empty-collection","invariant","subagent","panic"],"backgroundTag":"empty-result-set","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"}