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

> Source: <https://dev.to/sushilmagare10/ai-sdk-70160-started-enforcing-datapartschemas-your-loading-states-might-now-throw-31a5>
> Published: 2026-11-03 02:41:31+00:00

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](https://github.com/vercel/ai/issues/24241), fixed in [PR #24298](https://github.com/vercel/ai/pull/24298) and shipped in [ai 7.0.160](https://github.com/vercel/ai/releases/tag/ai%407.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](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat) 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 | 
| Loading 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](https://ai-sdk.dev/docs/ai-sdk-ui/streaming-data) use a progressive pattern: write `{ city, status: 'loading' }` 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 loading 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):

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

// Case 3: a loading update, then the final value under the same id
await run('3 loading update without weather, then final', [...start,
  ...text('t0', 'Checking...'),
  { type: 'data-weather', id: 'w1', data: { city: 'Berlin', status: 'loading' } },
  { 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:

``` js
const unionSchemas = {
  weather: z.discriminatedUnion('status', [
    z.object({ status: z.literal('loading'), 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 loading, 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?
