Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/fix-invalid-tool-call-input-raw-string.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"ai": patch
---

Wrap malformed tool call input in a JSON object instead of storing the raw string.

When a model returns invalid JSON as tool call input, `parseToolCall` previously stored the raw string as `input`. Providers like Amazon Bedrock require `toolUse.input` to be a JSON object, so the next-step API request would be rejected before the model could see the `tool-error` and retry. The invalid input is now stored as `{ rawInvalidInput: <original string> }`, which keeps the conversation history valid for all providers.
8 changes: 6 additions & 2 deletions packages/ai/src/generate-text/parse-tool-call.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ describe('parseToolCall', () => {
"dynamic": true,
"error": [AI_InvalidToolInputError: Invalid input for tool testTool: AI_JSONParseError: JSON parsing failed: Text: invalid json.
Error message: SyntaxError: Unexpected token 'i', "invalid json" is not valid JSON],
"input": "invalid json",
"input": {
"rawInvalidInput": "invalid json",
},
"invalid": true,
"providerExecuted": undefined,
"providerMetadata": undefined,
Expand Down Expand Up @@ -510,7 +512,9 @@ describe('parseToolCall', () => {
{
"dynamic": true,
"error": [AI_ToolCallRepairError: Error repairing tool call: Error: test error],
"input": "invalid json",
"input": {
"rawInvalidInput": "invalid json",
},
"invalid": true,
"providerExecuted": undefined,
"providerMetadata": undefined,
Expand Down
8 changes: 6 additions & 2 deletions packages/ai/src/generate-text/parse-tool-call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,13 @@ export async function parseToolCall<TOOLS extends ToolSet>({
});
}
} catch (error) {
// use parsed input when possible
// use parsed input when possible; fall back to a JSON object wrapper so
// providers that require object inputs (e.g. Amazon Bedrock) don't reject
// the next-step conversation history when the original input was malformed.
const parsedInput = await safeParseJSON({ text: toolCall.input });
const input = parsedInput.success ? parsedInput.value : toolCall.input;
const input = parsedInput.success
? parsedInput.value
: { rawInvalidInput: toolCall.input };
const tool = tools?.[toolCall.toolName];

// TODO AI SDK 6: special invalid tool call parts
Expand Down