aaif-goose/goose · error
Missing tool_use id
Error message
Missing tool_use id
What it means
response_to_message converts a Snowflake Cortex (Anthropic-compatible) non-streaming response into a Message. For each entry in content_list with type "tool_use" it requires a string field tool_use_id to key the tool_request block. If tool_use_id is missing or not a string, conversion fails with 'Missing tool_use id'.
Source
Thrown at crates/goose-provider-types/src/formats/snowflake.rs:249
}
}
};
// Process all content items in the list
for content in content_list {
match content.get("type").and_then(|t| t.as_str()) {
Some("text") => {
if let Some(text) = content.get("text").and_then(|t| t.as_str()) {
if !text.is_empty() {
message = message.with_text(text.to_string());
}
}
}
Some("tool_use") => {
let id = content
.get("tool_use_id")
.and_then(|i| i.as_str())
.ok_or_else(|| anyhow!("Missing tool_use id"))?;
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())View on GitHub (pinned to 3810898a74)
Solutions
- Log the raw response JSON and inspect the tool_use block for the tool_use_id key and its type
- Confirm you are hitting the real Snowflake Cortex endpoint whose tool_use blocks carry tool_use_id
- Update fixtures/mocks to include "tool_use_id" as a string on every tool_use block
- If upstream genuinely omits ids, skip the malformed block with a warn (see exampleFix) instead of failing the whole message
Example fix
// before
let id = content
.get("tool_use_id")
.and_then(|i| i.as_str())
.ok_or_else(|| anyhow!("Missing tool_use id"))?;
// after - skip malformed block, keep the rest of the response
let id = match content.get("tool_use_id").and_then(|i| i.as_str()) {
Some(id) => id,
None => {
tracing::warn!("skipping tool_use block without tool_use_id");
continue;
}
}; Defensive patterns
Strategy: validation
Validate before calling
// validate content_list before response_to_message
for block in content_list {
if block.get("type").and_then(|t| t.as_str()) == Some("tool_use")
&& block.get("tool_use_id").and_then(|i| i.as_str()).is_none()
{
anyhow::bail!("tool_use block without string tool_use_id: {block}");
}
} Type guard
fn tool_use_block_is_wellformed(block: &serde_json::Value) -> bool {
if block.get("type").and_then(|t| t.as_str()) != Some("tool_use") {
return true;
}
block.get("tool_use_id").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 tool_use id") => {
tracing::warn!("discarding malformed tool_use: {err}");
Message::assistant()
}
Err(err) => return Err(err),
} Prevention
- Keep Snowflake Cortex fixtures in the exact content_list wire shape (tool_use_id, not Anthropic-native id)
- Log raw Cortex responses at debug level in integration environments
- Re-verify response shapes after Cortex API version upgrades
- When adapting Anthropic-format traffic, write an explicit mapper instead of forwarding blocks unchanged
When it happens
Trigger: A Snowflake Cortex response whose content_list contains a {"type":"tool_use",...} block without a string tool_use_id field. Typical when the API response shape changes, when a proxy rewrites field names (Anthropic native uses "id" while this parser expects "tool_use_id"), or when the model emits a truncated/malformed tool call.
Common situations: Snowflake Cortex API version drift renaming id to tool_use_id or vice versa; testing against recorded fixtures that use the Anthropic wire format (id) instead of Snowflake's content_list format; responses from a Cortex SQL/function wrapper that drops ids.
Related errors
- Missing tool_use name
- Missing tool input
- Missing thinking content
- Missing thinking signature
- Missing redacted_thinking data
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/9d2da06312124d1a.
Report an issue: GitHub.