Hmbown/CodeWhale · error
tool result content
Error message
tool result content
What it means
A panic from `.expect("tool result content")` on a find_map over prepared messages in crates/tui/src/client.rs. The helper asserts that the projected request contains at least one ContentBlock::ToolResult and returns its content string; if no ToolResult block exists in any message, the Option is None and the test panics — meaning the adapter dropped, transformed, or mis-projected the tool result.
Solutions
- Inspect the prepared MessageRequest before the assertion (print blocks/variants) to see which variant the content landed in.
- Check recent changes to the adapter projection / dangling tool-call repair that could strip ToolResult blocks.
- Confirm the source request actually contains a ToolResult (request_with_tool_result builds one) and that model routing uses the expected adapter.
- Update the matcher if ToolResult was legitimately renamed/restructured in ContentBlock.
Example fix
// before
.find_map(|block| match block {
ContentBlock::ToolResult { content, .. } => Some(content.as_str()),
_ => None,
})
.expect("tool result content")
// after
.find_map(|block| match block {
ContentBlock::ToolResult { content, .. } => Some(content.as_str()),
_ => None,
})
.unwrap_or_else(|| panic!("no ToolResult block in: {messages:#?}")) Defensive patterns
Strategy: type-guard
Validate before calling
// rust: verify a ToolResult exists before asserting its content
assert!(request.messages.iter().any(|m| m.content.iter().any(|b| matches!(b, ContentBlock::ToolResult{..}))), "input lacks ToolResult"); Type guard
fn tool_result_content(msgs: &[MessageRequest]) -> Option<&str> {
msgs.iter().flat_map(|m| &m.content).find_map(|b| match b {
ContentBlock::ToolResult { content, .. } => Some(content.as_str()),
_ => None,
})
} Try / catch
let content = tool_result_content(&prepared.messages)
.unwrap_or_else(|| panic!("no ToolResult block after projection: {prepared:#?}")); Prevention
- After adapter/projection refactors, dump the prepared request before assertions.
- Keep ContentBlock matchers in sync with enum changes via exhaustive matches.
- Pin tests to behavior (repaired content present) rather than internal projection order.
When it happens
Trigger: Tests call request_with_tool_result/this helper and the adapter projection (e.g. dangling tool-call repair or adapter projection changes) removes or rewrites the ToolResult block so `messages.iter().flat_map(content).find_map(ToolResult)` finds nothing.
Common situations: Refactors of the adapter projection or tool-call repair logic that convert/strip ToolResult blocks; request construction that puts content in a different block variant; model-name changes routing to a different adapter.
Related errors
- Absolute path should not warn
- child assignment
- child-local search
- configured Web evidence tool
- expected authentication error, got
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/f0925fd4e8a7c94b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client.rs:8395
metadata: None,
thinking: None,
reasoning_effort: None,
stream: None,
temperature: None,
top_p: None,
}
}
fn tool_result_content(request: &MessageRequest) -> &str {
request
.messages
.iter()
.flat_map(|message| &message.content)
.find_map(|block| match block {
ContentBlock::ToolResult { content, .. } => Some(content.as_str()),
_ => None,
})
.expect("tool result content")
}
#[test]
fn model_bound_request_repairs_dangling_tool_call_before_adapter_projection() {
let client = client_with_config_secret_sentinels();
let mut request = request_with_tool_result("unused");
request.messages.pop();
let prepared = client.prepare_model_bound_request(request);
assert!(prepared.messages.iter().any(|message| {
message.content.iter().any(|block| {
matches!(
block,
ContentBlock::ToolResult {
tool_use_id,
content,
is_error: Some(true),View on GitHub (pinned to 73e0f67d83)