Skip to content

Commit 9edbab7

Browse files
mozmo15mozmo15felixweinberger
authored
fix(server): prioritize zod issues and format them (#1503)
Co-authored-by: mozmo15 <mozmo@mail.com> Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
1 parent e12cbd7 commit 9edbab7

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@modelcontextprotocol/sdk': patch
3+
---
4+
5+
Prioritize `error.issues[].message` over `error.message` in `getParseErrorMessage` so custom Zod error messages surface correctly. In Zod v4, `error.message` is a JSON blob of all issues, not a readable string.

src/server/zod-compat.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,23 +188,43 @@ export function normalizeObjectSchema(schema: AnySchema | ZodRawShapeCompat | un
188188
return undefined;
189189
}
190190

191+
function getDotPath(path: (string | number)[]) {
192+
if (path.length === 0) {
193+
return 'object root';
194+
}
195+
return path.reduce((acc, seg, index) => {
196+
if (index === 0) {
197+
return String(seg);
198+
}
199+
if (typeof seg === 'number') {
200+
return `${acc}[${seg}]`;
201+
}
202+
return `${acc}.${seg}`;
203+
}, '');
204+
}
205+
191206
// --- Error message extraction ---
192207
/**
193208
* Safely extracts an error message from a parse result error.
194209
* Zod errors can have different structures, so we handle various cases.
195210
*/
196211
export function getParseErrorMessage(error: unknown): string {
197212
if (error && typeof error === 'object') {
213+
// When present, prioritize zod issues and format as a message and path
214+
if ('issues' in error && Array.isArray(error.issues) && error.issues.length > 0) {
215+
return error.issues
216+
.map((i: { message: string; path?: (string | number)[] }) => {
217+
if (!i.path?.length) {
218+
return i.message;
219+
}
220+
return `${i.message} at ${getDotPath(i.path)}`;
221+
})
222+
.join('\n');
223+
}
198224
// Try common error structures
199225
if ('message' in error && typeof error.message === 'string') {
200226
return error.message;
201227
}
202-
if ('issues' in error && Array.isArray(error.issues) && error.issues.length > 0) {
203-
const firstIssue = error.issues[0];
204-
if (firstIssue && typeof firstIssue === 'object' && 'message' in firstIssue) {
205-
return String(firstIssue.message);
206-
}
207-
}
208228
// Fallback: try to stringify the error
209229
try {
210230
return JSON.stringify(error);

0 commit comments

Comments
 (0)