middleware
middleware copied to clipboard
[zod-openapi] use coerce in query does not respond proper error message when corresponding param not provided
When not using coerce:
common.openapi(
createRoute({
method: 'get',
path: '/dev',
request: {
query: z.object({
id: z.string(),
}),
},
responses: {
200: {
description: 'get dev id',
content: {
'application/json': {
schema: z.object({
id: z.string(),
}),
},
},
},
},
}),
async (c) => {
const { id } = c.req.valid('query')
return c.json(
{
id: '123',
},
200,
)
},
)
request http://localhost:3000/dev respond with:
{
"success": false,
"error": {
"issues": [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"id"
],
"message": "Required"
}
],
"name": "ZodError"
}
}
When using coerce:
common.openapi(
createRoute({
method: 'get',
path: '/dev',
request: {
query: z.object({
id: z.coerce.bigint(),
}),
},
responses: {
200: {
description: 'get dev id',
content: {
'application/json': {
schema: z.object({
id: z.string(),
}),
},
},
},
},
}),
async (c) => {
const { id } = c.req.valid('query')
return c.json(
{
id: '123',
},
200,
)
},
)
request http://localhost:3000/dev respond with:
Internal Server Error
Hi @zhuscat
This a Zod matter and a Zod's limitation, and you can write like the following:
const schema = app.openapi(
createRoute({
method: 'get',
path: '/dev',
request: {
query: z.object({
id: z.any().transform((value, ctx) => {
try {
return BigInt(value)
} catch (error) {
ctx.addIssue({
code: 'invalid_type',
expected: 'unknown',
received: value,
message: `Can't be parsed to BigInt`
})
}
})
})
},
// ...
These are good references for you:
- https://github.com/colinhacks/zod/discussions/1897
- https://github.com/colinhacks/zod/discussions/1856