-
Notifications
You must be signed in to change notification settings - Fork 171
Description
Expected Behavior
In the following example:
const lambdaHandler = async (
event: ParsedResult<JobsRequest>,
context: Context
): Promise<APIGatewayProxyResult> => {
if (!event.success) {
return response(400, JSON.stringify((event.error.cause as ZodError).errors));
}
return response(200, `Parsed Event: ${JSON.stringify(event)}`);
};
const handler = middy(lambdaHandler).use(
parser({ schema: jobsRequestSchema, envelope: ApiGatewayEnvelope, safeParse: true })
);
event.error.cause
should contain a ZodError, and calling event.error.cause.errors
should return something like:
[
{
"code": "too_small",
"minimum": 0,
"type": "number",
"inclusive": false,
"exact": false,
"message": "ID must be positive",
"path": [
"id"
]
}
]
Current Behavior
event.error.cause
contains a ParseError, which contains another cause which contains the ZodError.
So to get to the ZodError, you have to call event.error.cause.cause
Code snippet
import { APIGatewayProxyResult } from "aws-lambda";
import { ApiGatewayEnvelope } from "@aws-lambda-powertools/parser/envelopes";
import { z } from "zod";
import middy from "@middy/core";
import { parser } from "@aws-lambda-powertools/parser/middleware";
import { ParsedResult } from "@aws-lambda-powertools/parser/types";
const response = (status: number, body: string): APIGatewayProxyResult => ({
statusCode: status,
body,
headers: {
"content-type": "application/json",
},
});
const jobsRequestSchema = z.object({
id: z.number().positive("ID must be positive"),
from: z.coerce.date(),
to: z.coerce.date(),
});
type JobsRequest = z.infer<typeof jobsRequestSchema>;
const lambdaHandler = async (event: ParsedResult<JobsRequest>): Promise<APIGatewayProxyResult> => {
if (!event.success) {
const errorResponse = {
error_cause: event.error.cause,
error_cause_cause: event.error.cause?.cause,
};
return response(400, JSON.stringify(errorResponse));
}
return response(200, `Hello World, Parsed Event: ${JSON.stringify(event)}`);
};
const handler = middy(lambdaHandler).use(
parser({ schema: jobsRequestSchema, envelope: ApiGatewayEnvelope, safeParse: true })
);
module.exports = { handler };
POSTing the following body:
{
"id": -1,
"from": "2024-01-01",
"to": "2024-01-02"
}
returns:
{
"error_cause": {
"name": "ParseError"
},
"error_cause_cause": {
"issues": [
{
"code": "too_small",
"minimum": 0,
"type": "number",
"inclusive": false,
"exact": false,
"message": "ID must be positive",
"path": [
"id"
]
}
],
"name": "ZodError"
}
}
Steps to Reproduce
Create a lambda with the above code in your handler.ts
Possible Solution
I haven't tested if this affects other Envelopes as well or not, but the apigw.ts
safeParse
function here
calls Envelope.safeParse(...)
on line 30
and then creates a new ParseError
on line 35, with the parsedBody.error
as the cause.
parsedBody.error
is itself already a ParseError
from here on line 64, and that has the ZodError
as its cause.
So depending on whether it affects all envelopes or not, we could maybe look at changing line 64 in envelope.ts
to be error: parsed.error
instead of creating a new ParseError
with a cause?
Powertools for AWS Lambda (TypeScript) version
latest
AWS Lambda function runtime
18.x
Packaging format used
npm
Execution logs
No response
Metadata
Metadata
Assignees
Labels
Type
Projects
Status