aaif-goose/goose · error
Missing thinking content
Error message
Missing thinking content
What it means
response_to_message handles Snowflake Cortex thinking blocks (extended reasoning). A content_list entry of type "thinking" must carry a string field thinking (the reasoning text). If the key is missing or not a string, conversion fails with 'Missing thinking content'. The signature is required next, so reaching that error means this field was fine.
Source
Thrown at crates/goose-provider-types/src/formats/snowflake.rs:268
let name = content
.get("name")
.and_then(|n| n.as_str())
.ok_or_else(|| anyhow!("Missing tool_use name"))?
.to_string();
let input = content
.get("input")
.ok_or_else(|| anyhow!("Missing tool input"))?
.clone();
let tool_call = CallToolRequestParams::new(name).with_arguments(object(input));
message = message.with_tool_request(id, Ok(tool_call));
}
Some("thinking") => {
let thinking = content
.get("thinking")
.and_then(|t| t.as_str())
.ok_or_else(|| anyhow!("Missing thinking content"))?;
let signature = content
.get("signature")
.and_then(|s| s.as_str())
.ok_or_else(|| anyhow!("Missing thinking signature"))?;
message = message.with_thinking(thinking, signature);
}
Some("redacted_thinking") => {
let data = content
.get("data")
.and_then(|d| d.as_str())
.ok_or_else(|| anyhow!("Missing redacted_thinking data"))?;
message = message.with_redacted_thinking(data);
}
_ => {
// Ignore unrecognized content types
}
}
}View on GitHub (pinned to 3810898a74)
Solutions
- Log the raw thinking block and confirm the "thinking" key exists and holds a string
- Verify the model/endpoint actually produces Snowflake Cortex-format thinking blocks (thinking + signature at the block level)
- Update fixtures to include both "thinking" and "signature"
- If partial thinking blocks are expected from your endpoint, skip blocks missing the text instead of failing the message
Example fix
// before
let thinking = content
.get("thinking")
.and_then(|t| t.as_str())
.ok_or_else(|| anyhow!("Missing thinking content"))?;
// after - skip incomplete thinking blocks
let thinking = match content.get("thinking").and_then(|t| t.as_str()) {
Some(t) => t,
None => {
tracing::warn!("skipping thinking block without content");
continue;
}
}; Defensive patterns
Strategy: validation
Validate before calling
for block in content_list {
if block.get("type").and_then(|t| t.as_str()) == Some("thinking")
&& block.get("thinking").and_then(|t| t.as_str()).is_none()
{
anyhow::bail!("thinking block without string thinking field: {block}");
}
} Type guard
fn thinking_block_has_text(block: &serde_json::Value) -> bool {
if block.get("type").and_then(|t| t.as_str()) != Some("thinking") {
return true;
}
block.get("thinking").and_then(|v| v.as_str()).is_some()
} Try / catch
match response_to_message(&response) {
Ok(msg) => msg,
Err(err) if err.to_string().contains("Missing thinking content") => {
tracing::warn!("response with unusable thinking block: {err}");
Message::assistant()
}
Err(err) => return Err(err),
} Prevention
- Confirm the model variant actually emits Cortex-format thinking blocks before enabling extended reasoning
- Map Anthropic-native thinking blocks explicitly when bridging formats
- Include thinking text (and signature) in every reasoning fixture
When it happens
Trigger: A {"type":"thinking",...} block without a string "thinking" member — e.g. a signature-only block, a renamed field (Anthropic native uses "thinking" inside a different envelope), or redacted/placeholder thinking emitted without text.
Common situations: Switching a Cortex model to a reasoning variant whose response schema differs from expectations; proxies forwarding Anthropic-native thinking blocks into content_list without adaptation; fixtures with signature but no thinking text.
Related errors
- Missing thinking signature
- Missing redacted_thinking data
- Missing tool_use id
- Missing tool_use name
- Missing tool input
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/4743730fe5b34b00.
Report an issue: GitHub.