{"record":{"id":"4da23b58ae6216cd","repo":"aaif-goose/goose","slug":"missing-redacted-thinking-data-4da23b","errorCode":null,"errorMessage":"Missing redacted_thinking data","messagePattern":"Missing redacted_thinking data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/goose-provider-types/src/formats/snowflake.rs","lineNumber":279,"sourceCode":"                let tool_call = CallToolRequestParams::new(name).with_arguments(object(input));\n                message = message.with_tool_request(id, Ok(tool_call));\n            }\n            Some(\"thinking\") => {\n                let thinking = content\n                    .get(\"thinking\")\n                    .and_then(|t| t.as_str())\n                    .ok_or_else(|| anyhow!(\"Missing thinking content\"))?;\n                let signature = content\n                    .get(\"signature\")\n                    .and_then(|s| s.as_str())\n                    .ok_or_else(|| anyhow!(\"Missing thinking signature\"))?;\n                message = message.with_thinking(thinking, signature);\n            }\n            Some(\"redacted_thinking\") => {\n                let data = content\n                    .get(\"data\")\n                    .and_then(|d| d.as_str())\n                    .ok_or_else(|| anyhow!(\"Missing redacted_thinking data\"))?;\n                message = message.with_redacted_thinking(data);\n            }\n            _ => {\n                // Ignore unrecognized content types\n            }\n        }\n    }\n\n    Ok(message)\n}\n\n/// Extract usage information from Snowflake's API response\npub fn get_usage(data: &Value) -> Result<Usage> {\n    // Extract usage data if available\n    if let Some(usage) = data.get(\"usage\") {\n        let input_tokens = usage\n            .get(\"input_tokens\")\n            .and_then(|v| v.as_u64())","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-provider-types/src/formats/snowflake.rs#L261-L297","documentation":"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'.","triggerScenarios":"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.","commonSituations":"Safety-filtered reasoning models returning redacted blocks; endpoint version bump changing the field name; fixtures that mark redacted thinking without copying the data payload.","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"],"exampleFix":"// before\nlet data = content\n    .get(\"data\")\n    .and_then(|d| d.as_str())\n    .ok_or_else(|| anyhow!(\"Missing redacted_thinking data\"))?;\n\n// after - skip unusable redacted blocks\nlet data = match content.get(\"data\").and_then(|d| d.as_str()) {\n    Some(d) => d,\n    None => {\n        tracing::warn!(\"skipping redacted_thinking block without data\");\n        continue;\n    }\n};","handlingStrategy":"validation","validationCode":"for block in content_list {\n    if block.get(\"type\").and_then(|t| t.as_str()) == Some(\"redacted_thinking\")\n        && block.get(\"data\").and_then(|d| d.as_str()).is_none()\n    {\n        anyhow::bail!(\"redacted_thinking block without string data: {block}\");\n    }\n}","typeGuard":"fn redacted_thinking_has_data(block: &serde_json::Value) -> bool {\n    if block.get(\"type\").and_then(|t| t.as_str()) != Some(\"redacted_thinking\") {\n        return true;\n    }\n    block.get(\"data\").and_then(|v| v.as_str()).is_some()\n}","tryCatchPattern":"match response_to_message(&response) {\n    Ok(msg) => msg,\n    Err(err) if err.to_string().contains(\"Missing redacted_thinking data\") => {\n        tracing::warn!(\"dropping response with empty redacted_thinking: {err}\");\n        Message::assistant()\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["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"],"tags":["rust","snowflake","cortex","reasoning","parsing"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}