Hmbown/CodeWhale · error
single target returned a result
Error message
single target returned a result
What it means
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.
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.
Example fix
// before
results.pop().expect("single target returned a result")
// after
results.pop().ok_or_else(|| ToolError::execution_failed("single target returned no result"))? Defensive patterns
Strategy: validation
Validate before calling
// Validate target list before dispatch
if targets.is_empty() {
return Err(ToolError::execution_failed("followup requires at least one target"));
} Type guard
fn single_result(results: Vec<serde_json::Value>) -> Option<serde_json::Value> {
if results.len() == 1 { results.into_iter().next() } else { None }
} Try / catch
// Fallible pop instead of expect
let payload = results.pop()
.ok_or_else(|| ToolError::execution_failed("single target returned no result"))?; Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- runtime checked
- bounded to model output cap
- event recovery buffer fits u64
- event transaction runs once
- finite points
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/b416eb7c6cdfffef.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/subagent/coord.rs:506
));
}
ids
};
let mut seen = std::collections::HashSet::new();
targets.retain(|target| seen.insert(target.clone()));
let mut results = Vec::new();
let mut errors = Vec::new();
// Each mutation and both hierarchy checks share the manager write lock.
// A target failure cannot erase successful results from another target.
for target in targets {
match self.followup_one(&target, message, context).await {
Ok(payload) => results.push(payload),
Err(error) if single.is_some() => return Err(error),
Err(error) => errors.push(json!({"from": target, "error": error.to_string()})),
}
}
let payload = if single.is_some() {
results.pop().expect("single target returned a result")
} else {
json!({"action": "followup", "results": results, "errors": errors})
};
let mut result = ToolResult::json(&payload)
.map_err(|error| ToolError::execution_failed(error.to_string()))?;
result.metadata = Some(payload.clone());
Ok(result)
}
}
// ── agents/interrupt ─────────────────────────────────────────────────────
pub struct AgentsInterruptTool {
manager: SharedSubAgentManager,
/// Optional caller identity for fail-closed self-interrupt checks.
caller_agent_id: Option<String>,
}
View on GitHub (pinned to 433685b202)