aaif-goose/goose · warning
Missing redacted_thinking data
Error message
Missing redacted_thinking data
What it means
Snowflake Cortex can return encrypted reasoning as a content_list block of type redacted_thinking. The parser requires its data field (a string payload) to reconstruct the block via with_redacted_thinking. A redacted_thinking block without a string data key fails with 'Missing redacted_thinking data'.
Source
Thrown at crates/goose-provider-types/src/formats/snowflake.rs:279
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
}
}
}
Ok(message)
}
/// Extract usage information from Snowflake's API response
pub fn get_usage(data: &Value) -> Result<Usage> {
// Extract usage data if available
if let Some(usage) = data.get("usage") {
let input_tokens = usage
.get("input_tokens")
.and_then(|v| v.as_u64())View on GitHub (pinned to 3810898a74)
Solutions
- Inspect the raw redacted_thinking block and confirm the data key name and type
- Check for an upstream API schema change and align the parser if the field was renamed
- Fix fixtures to include "data"
- If the block is unfixable, skip it with a warn — losing a redacted-thinking block is safer than failing the message
Example fix
// before
let data = content
.get("data")
.and_then(|d| d.as_str())
.ok_or_else(|| anyhow!("Missing redacted_thinking data"))?;
// after - skip unusable redacted blocks
let data = match content.get("data").and_then(|d| d.as_str()) {
Some(d) => d,
None => {
tracing::warn!("skipping redacted_thinking block without data");
continue;
}
}; Defensive patterns
Strategy: validation
Validate before calling
for block in content_list {
if block.get("type").and_then(|t| t.as_str()) == Some("redacted_thinking")
&& block.get("data").and_then(|d| d.as_str()).is_none()
{
anyhow::bail!("redacted_thinking block without string data: {block}");
}
} Type guard
fn redacted_thinking_has_data(block: &serde_json::Value) -> bool {
if block.get("type").and_then(|t| t.as_str()) != Some("redacted_thinking") {
return true;
}
block.get("data").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 redacted_thinking data") => {
tracing::warn!("dropping response with empty redacted_thinking: {err}");
Message::assistant()
}
Err(err) => return Err(err),
} Prevention
- Track Cortex release notes for redacted-thinking schema changes
- Copy the full data payload when fixture-recording redacted blocks
- Treat redacted blocks as best-effort: skipping one is usually safer than failing the turn
When it happens
Trigger: The model emits {"type":"redacted_thinking"} with no data member, or data is not a string (null, object). Rare; usually indicates an API change in the redacted-thinking envelope or a proxy mangling the block.
Common situations: Safety-filtered reasoning models returning redacted blocks; endpoint version bump changing the field name; fixtures that mark redacted thinking without copying the data payload.
Related errors
- Missing thinking content
- Missing thinking signature
- 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/4da23b58ae6216cd.
Report an issue: GitHub.