cd /news/ai-tools/ai-sdk-7-0-160-started-enforcing-dat… · home › topics › ai-tools › article
[ARTICLE · art-162873] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=· neutral

AI SDK 7.0.160 Started Enforcing dataPartSchemas. Your Loading States Might Now Throw

A developer's testing of the Vercel AI SDK found that ai 7.0.160 turned on validation for `dataPartSchemas` passed to `useChat` and `Chat` that had previously never run, so streams that worked on 7.0.159 can now fail with a `TypeValidationError`. The fix for issue #24241 (PR #24298) looks up schemas by the bare part name, meaning every chunk — including transient parts and progressive loading updates — is now checked, and a schema written only for the final shape rejects the loading chunk. The developer recommends schemas that describe every state the server sends, such as a discriminated union on `status`, which kept the same stream in `status: ready` across versions.

by read3 min views3 publishedNov 3, 2026

If you pass dataPartSchemas to useChat and bump ai to 7.0.160 or later, a chat that worked yesterday can end up in status: 'error' with a TypeValidationError. You didn't change anything. Your schemas just started running.

useChat and Chat accept dataPartSchemas, keyed by the bare part name ( weather for a data-weather part). The stream processor looked the schema up by the full chunk type (data-weather), so the lookup always missed and streamed data parts were never validated. That's issue #24241, fixed in PR #24298 and shipped in ai 7.0.160: "Invalid data parts now raise a TypeValidationError."

So a patch release turned on a check that was configured but never ran.

I didn't want to guess at the edge cases, so I drove the Chat class from @ai-sdk/react with a fake transport that replays fixed UI message chunks. No model, no network. useChat runs on that same class (its chat option even takes an existing Chat instance), so the stream handling is the same code path. I ran the same script against ai 7.0.159 with @ai-sdk/react 4.0.163, ai 7.0.162 with @ai-sdk/react 4.0.166, and ai 6.0.322 with @ai-sdk/react 3.0.325, all with zod 4.6.7 on Node 20.19.2.

Stream 7.0.159 7.0.162
Valid data-weather part ready ready
city: 42 , then some text ready, bad data kept in parts , text arrives error, no assistant message at all
update without weather , then the final value ready error, earlier text kept, final value lost
Transient part that fails the schema ready, onData called error, onData not called
data-notice part with no schema ready ready

On 6.0.322 every row matched the 7.0.159 column: bad data went through without an error.

The streaming data docs use a progressive pattern: write { city, status: '' } first, then write to the same id again with the real value. The docs type weather as optional (weather?: string), which fits that pattern. But if your zod schema was written for the finished shape, the chunk fails now. Here's the excerpt from my test script (start and end are the start/finish chunks, text() writes one text part, and run() sends a message through Chat with these chunks):

const strictSchemas = {
  weather: z.object({
    city: z.string(),
    weather: z.string(),
    status: z.enum(['', 'success']),
  }),
};

// Case 3: a  update, then the final value under the same id
await run('3  update without weather, then final', [...start,
  ...text('t0', 'Checking...'),
  { type: 'data-weather', id: 'w1', data: { city: 'Berlin', status: '' } },
  { type: 'data-weather', id: 'w1', data: { city: 'Berlin', weather: 'sunny', status: 'success' } }, ...end]);

On 7.0.162 this ended with Type validation failed for message.parts[2].data (data-weather, id: "w1"). The "Checking..." text that streamed before it stayed in the message, the final value never arrived, and chat.status was error.

Every chunk is checked, not just the last one per id. Transient parts too, even though they never land in message.parts.

Make the schema describe every state the server actually sends. A discriminated union keeps the final shape strict:

const unionSchemas = {
  weather: z.discriminatedUnion('status', [
    z.object({ status: z.literal(''), city: z.string() }),
    z.object({ status: z.literal('success'), city: z.string(), weather: z.string() }),
  ]),
};

With this schema the same stream finished with status: ready on both versions, and the part ended up as { city: 'Berlin', weather: 'sunny', status: 'success' }.

Before you upgrade, I'd do three things:

dataPartSchemas. data-* type in there, check every writer.write() on the server against its schema, including , progress and transient writes.error from useChat. In my runs a failed part stopped the whole response, so a silent failure here looks like a chat that just stops. Data parts with no schema aren't checked at all, so a schema-less type won't start failing.

I'd rather have the error than let city: 42 slip into message.parts without a word, which is what 7.0.159 did. Have you hit this one after updating, or were your schemas already matching what the server sends?

── more in #ai-tools 4 stories · sorted by recency
── more on @vercel 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/ai-sdk-7-0-160-start…] indexed:0 read:3min 2026-11-03 · —