Skip to content

Commit eb8d1cb

Browse files
authored
Fix(ai): correctly valiate empty arrays (#10093)
## Background The `validateUIMessages` and `safeValidateUIMessages` functions don't properly check for arrays being not-empty, ## Summary Updated the zod schema to catch empty arrays passed in messages. ## Manual Verification Wrote tests with empty arrays throwing errors. ## Related Issues Fixes #10003
1 parent c95fcd2 commit eb8d1cb

File tree

3 files changed

+347
-262
lines changed

3 files changed

+347
-262
lines changed

.changeset/mean-mugs-swim.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'ai': patch
3+
---
4+
5+
fix not catching of empty arrays in validateUIMessage

packages/ai/src/ui/validate-ui-messages.test.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,55 @@ describe('validateUIMessages', () => {
2727
[AI_InvalidArgumentError: Invalid argument for parameter messages: messages parameter must be provided]
2828
`);
2929
});
30+
31+
it('should throw TypeValidationError when messages array is empty', async () => {
32+
await expect(
33+
validateUIMessages({
34+
messages: [],
35+
}),
36+
).rejects.toThrowErrorMatchingInlineSnapshot(`
37+
[AI_TypeValidationError: Type validation failed: Value: [].
38+
Error message: [
39+
{
40+
"origin": "array",
41+
"code": "too_small",
42+
"minimum": 1,
43+
"inclusive": true,
44+
"path": [],
45+
"message": "Messages array must not be empty"
46+
}
47+
]]
48+
`);
49+
});
50+
51+
it('should throw TypeValidationError when message has empty parts array', async () => {
52+
await expect(
53+
validateUIMessages({
54+
messages: [
55+
{
56+
id: '1',
57+
role: 'user',
58+
parts: [],
59+
},
60+
],
61+
}),
62+
).rejects.toThrowErrorMatchingInlineSnapshot(`
63+
[AI_TypeValidationError: Type validation failed: Value: [{"id":"1","role":"user","parts":[]}].
64+
Error message: [
65+
{
66+
"origin": "array",
67+
"code": "too_small",
68+
"minimum": 1,
69+
"inclusive": true,
70+
"path": [
71+
0,
72+
"parts"
73+
],
74+
"message": "Message must contain at least one part"
75+
}
76+
]]
77+
`);
78+
});
3079
});
3180

3281
describe('metadata', () => {
@@ -1194,6 +1243,33 @@ describe('safeValidateUIMessages', () => {
11941243
);
11951244
});
11961245

1246+
it('should return failure result when messages array is empty', async () => {
1247+
const result = await safeValidateUIMessages({
1248+
messages: [],
1249+
});
1250+
1251+
expectToBe(result.success, false);
1252+
expect(result.error.name).toBe('AI_TypeValidationError');
1253+
expect(result.error.message).toContain('Type validation failed');
1254+
expect(result.error.message).toContain('Messages array must not be empty');
1255+
});
1256+
1257+
it('should return failure result when message has empty parts array', async () => {
1258+
const result = await safeValidateUIMessages({
1259+
messages: [
1260+
{
1261+
id: '1',
1262+
role: 'user',
1263+
parts: [],
1264+
},
1265+
],
1266+
});
1267+
1268+
expectToBe(result.success, false);
1269+
expect(result.error.name).toBe('AI_TypeValidationError');
1270+
expect(result.error.message).toContain('Type validation failed');
1271+
});
1272+
11971273
it('should return failure result when metadata validation fails', async () => {
11981274
const result = await safeValidateUIMessages<UIMessage<{ foo: string }>>({
11991275
messages: [

0 commit comments

Comments
 (0)