Skip to content

BedrockToolUseSchema rejects valid contentBlockStart events under Zod ≥ 4.4.0 #14892

@raphaeleidus

Description

@raphaeleidus

Description

BedrockToolUseSchema rejects valid contentBlockStart events under Zod ≥ 4.4.0 (input is missing, not undefined)

Summary

Every tool call made through @ai-sdk/amazon-bedrock fails validation when the project resolves zod@>=4.4.0. Bedrock's Converse Stream API does not send input on the contentBlockStart event for a tool use — only toolUseId and name — and the JSON args arrive later in contentBlockDelta events. The provider's BedrockToolUseSchema declares input: z.unknown(), which used to accept a missing key but now (under Zod v4.4.0+) requires the key to be present. Result: the very first event of every tool call throws AI_TypeValidationError.

Reproduction

Any tool invocation against a Bedrock model triggers the error. The thrown payload is exactly:

AI_TypeValidationError: Type validation failed: Value: {"contentBlockStart":{"contentBlockIndex":0,"start":{"toolUse":{"name":"getNews","toolUseId":"tooluse_3d8KvhYE28U35U1DPMYnLW","type":"tool_use"}}}}.
Error message: [
  {
    "code": "invalid_type",
    "expected": "nonoptional",
    "path": ["contentBlockStart", "start", "toolUse", "input"],
    "message": "Invalid input: expected nonoptional, received undefined"
  }
]

The error is reproducible with a ~30 line script that feeds a real Bedrock contentBlockStart payload through the provider's schema; the same payload passes under zod@4.3.6 and fails under zod@4.4.0.

Root Cause

In amazon-bedrock-chat-language-model.ts (line ~1075 on the v5 branch; same shape in the v4 stable bundle at dist/index.mjs:1495):

var BedrockToolUseSchema = z.object({
  toolUseId: z.string(),
  name: z.string(),
  input: z.unknown(),   // <- requires the key under Zod v4
});
  • Under Zod v3 (and Zod v4 ≤ 4.3.x), z.unknown() accepted a missing key — equivalent to z.unknown().optional().
  • Under Zod v4 ≥ 4.4.0, z.unknown() requires the key to be present (expected: "nonoptional" when undefined).

Bedrock's wire format never includes input on contentBlockStart; the args are streamed in subsequent contentBlockDelta.delta.toolUse.input chunks. So the schema is incompatible with the protocol it's parsing.

Versions Affected

This package switched its imports from "zod" to "zod/v4" at the 3.0.0 boundary, and the schema has been unchanged since:

Version Imports from Schema Bug under zod ≥ 4.4.0
2.2.12 (last 2.x stable) "zod" input: z.unknown() n/a (zod v3)
3.0.04.0.98 (latest stable) "zod/v4" input: z.unknown() yes
5.0.0-beta.46 (latest beta) "zod/v4" input: z.unknown() yes

There is no published version of @ai-sdk/amazon-bedrock on the v3/v4/v5 line that survives zod@>=4.4.0.

Why this surfaced now

zod@4.4.0 tightened the semantics of z.unknown() in object shapes: a key declared as z.unknown() is no longer implicitly optional. This is arguably a regression in a minor release, but until/unless it's reverted upstream, every consumer that relied on the old z.unknown() semantics needs to declare .optional() (or .nullish()) explicitly. The Bedrock provider is one of those consumers.

Proposed Fix

One-character change — make the field explicitly optional, since the protocol genuinely doesn't send it on this event:

var BedrockToolUseSchema = z.object({
  toolUseId: z.string(),
  name: z.string(),
  input: z.unknown().optional(),  // or .nullish()
});

I verified the fix by patching the installed copy with patch-package; the validation passes for real Bedrock contentBlockStart events and downstream contentBlockDelta parsing is unaffected (it already handles input being assembled from deltas).

If there are other z.unknown() fields in Bedrock schemas that map to keys Bedrock may legitimately omit, those would benefit from the same audit — contentBlockStart.start.toolUse.input is the one I confirmed broken.

Workarounds for downstream users

Until a fix lands, consumers have to either:

  1. Pin zod to ^4.3.x (and add an overrides entry to keep transitive resolutions on 4.3.x).
  2. Apply a patch-package patch that adds .optional() to the input field of BedrockToolUseSchema.

Pinning the provider to 2.2.12 is not a real option because its peerDeps (zod@^3, @ai-sdk/provider@1.1.3) are incompatible with current ai / @ai-sdk/provider major versions.

Environment

  • @ai-sdk/amazon-bedrock: 4.0.97 (also confirmed on 4.0.98 and 5.0.0-beta.46)
  • zod: 4.4.0 (works on 4.3.6)
  • ai: ^6
  • Node.js: any
  • Model: Claude (via Bedrock Converse Stream); reproduces on every tool-using model.

AI SDK Version

  • @ai-sdk/amazon-bedrock: 4.0.97 (also confirmed on 4.0.98 and 5.0.0-beta.46)
  • zod: 4.4.0 (works on 4.3.6)
  • ai: ^6

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions