aaif-goose/goose · error
Missing tool_use name
Error message
Missing tool_use name
What it means
While parsing a Snowflake Cortex content_list entry of type "tool_use", response_to_message requires a string name field (the tool name to put into CallToolRequestParams). A tool_use block whose name key is absent or not a string fails with 'Missing tool_use name'. Note the id is extracted first, so this error implies tool_use_id was present.
Source
Thrown at crates/goose-provider-types/src/formats/snowflake.rs:253
// 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())
.ok_or_else(|| anyhow!("Missing thinking content"))?;
let signature = content
.get("signature")
.and_then(|s| s.as_str())View on GitHub (pinned to 3810898a74)
Solutions
- Inspect the raw content_list entry: confirm "name" exists and is a JSON string
- If the field was renamed upstream (e.g. tool_name), align the parser/config with the current Snowflake Cortex schema
- Fix test fixtures to include "name" on tool_use blocks
- If upstream cannot be corrected, skip the block with a warn instead of aborting the whole conversion
Example fix
// before
let name = content
.get("name")
.and_then(|n| n.as_str())
.ok_or_else(|| anyhow!("Missing tool_use name"))?
.to_string();
// after - tolerate a missing name with a placeholder and a warning
let name = match content.get("name").and_then(|n| n.as_str()) {
Some(n) => n.to_string(),
None => {
tracing::warn!("tool_use block without name; using placeholder");
"unknown_tool".to_string()
}
}; Defensive patterns
Strategy: validation
Validate before calling
for block in content_list {
if block.get("type").and_then(|t| t.as_str()) == Some("tool_use")
&& block.get("name").and_then(|n| n.as_str()).is_none()
{
anyhow::bail!("tool_use block without string name: {block}");
}
} Type guard
fn tool_use_has_name(block: &serde_json::Value) -> bool {
if block.get("type").and_then(|t| t.as_str()) != Some("tool_use") {
return true;
}
block.get("name").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 name") => {
tracing::warn!("tool call without name dropped: {err}");
Message::assistant()
}
Err(err) => return Err(err),
} Prevention
- Always emit "name" alongside "tool_use_id" in mocks and recorded traffic
- Validate tool schemas advertised to Cortex so the model can only call named tools
- Watch for schema renames (name vs tool_name) after endpoint upgrades
When it happens
Trigger: A {"type":"tool_use","tool_use_id":"..."} block in content_list with no name key or a non-string name (null, number). Occurs with truncated model output, API shape drift, or gateways that forward tool calls without resolving the tool name.
Common situations: Cortex returning a partially-formed tool call (name elided under token pressure); fixtures written with only id+input; schema change renaming name to tool_name.
Related errors
- Missing tool_use id
- 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/2a03ca0ebcf500ee.
Report an issue: GitHub.