-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
Describe the bug
Bedrock's Converse API rejects tool calls when the model invokes a tool with no arguments:
ValidationException: The value at messages.1.content.0.toolUse.input is empty.
To Reproduce
- Use the
aws_bedrockprovider - Resume a session from the session DB where a tool call had null/missing arguments, or switch from Google/Vertex provider to Bedrock mid-session
- On the next API call, Bedrock returns
ValidationException
The primary path: tool_result_serde.rs:40 maps Value::Null => None during session deserialization, feeding None arguments into the Bedrock format handler. In a pure Bedrock session without resume, from_bedrock_content_block always produces Some(map), so None arguments do not originate from Bedrock responses.
Expected behavior
No-argument tool calls should send {} (empty JSON object) as toolUse.input.
Root cause
In crates/goose/src/providers/formats/bedrock.rs (lines 75 and 90), both ToolRequest and FrontendToolRequest convert arguments via:
.input(to_bedrock_json(&Value::from(call.arguments.clone())))When call.arguments (Option<JsonObject>) is None, Value::from(None) yields Value::Null, which to_bedrock_json converts to Document::Null. The AWS SDK builder accepts this, but the Bedrock API rejects it.
tool_result_serde.rs:40 is the primary source of None arguments: it explicitly maps Value::Null => None when deserializing tool calls from the session database.
Suggested fix:
let input_val = call.arguments.clone()
.map(Value::Object)
.unwrap_or_else(|| Value::Object(Default::default()));Both ToolRequest (line 75) and FrontendToolRequest (line 90) need this change.
Retry behavior (secondary issue)
The ValidationException for empty input is miscategorized in the error handling chain. In crates/goose/src/providers/bedrock.rs (line 301), unmatched ValidationException variants fall through to the catch-all:
err => ProviderError::ServerError(format!("Failed to call Bedrock: {:?}", err))ServerError is retryable per should_retry() in crates/goose/src/providers/retry.rs. Retries are futile because the same deserialized None arguments are re-sent each attempt. After exhausting retries, the session is unrecoverable.
This ValidationException is a deterministic client-side serialization bug, not a transient server error. It should either be prevented by the primary fix above, or mapped to a non-retryable error variant (e.g., ExecutionError).
Please provide the following information
- OS & Arch: macOS (Apple Silicon)
- Interface: CLI
- Version: v1.28.0 (also confirmed on current main)
- Extensions enabled: developer, code-analyze, context7, brave_search, aptu
- Provider & Model: aws_bedrock / global.anthropic.claude-sonnet-4-6
Additional context
- The ToolUseBlock API reference documents
inputas a required field typed as JSON document - aws/aws-sdk-php#2962 is the same class of bug in the PHP SDK: empty/null input rejected by the Converse API
- vercel/ai#5527 discusses defaulting to
{}for tools with no parameters in the Vercel AI SDK's Bedrock provider - No existing tests cover the
None-arguments case