Skip to content

Bug: Zod schema Cognito Trigger Event preferredRole property may be null #4250

@bdellegrazie

Description

@bdellegrazie

Expected Behavior

The event parses successfully.

Current Behavior

In the initial request event being sent from Cognito for the pre token generation trigger lambda, the preferredRole and claimsAndScopeOverrideDetails values may be null causing the parser to fail validation.

Example:

{
    "version": "2",
    "triggerSource": "TokenGeneration_Authentication",
    "region": "eu-west-2",
    "userPoolId": "eu-west-2_POOL_ID",
    "userName": "fakeUsername",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "fake-client-id"
    },
    "request": {
        "userAttributes": {
            "sub": "0720b425-7607-41f2-b476-b03dd6a3c167",
            "cognito:email_alias": "fake.username@example.com",
            "cognito:user_status": "CONFIRMED",
            "email_verified": "true",
            "name": "Fake Username",
            "phone_number_verified": "true",
            "cognito:phone_number_alias": "+15555555555",
            "phone_number": "+15555555555",
            "family_name": "Username",
            "email": "fake.username@example.com"
        },
        "groupConfiguration": {
            "groupsToOverride": [
                "example-group"
            ],
            "iamRolesToOverride": [],
            "preferredRole": null
        },
        "scopes": [
            "aws.cognito.signin.user.admin"
        ]
    },
    "response": {
        "claimsAndScopeOverrideDetails": null
    }
}

Code snippet

import type {
  Context,
  PreTokenGenerationV2TriggerEvent,
} from "aws-lambda";
import type { LambdaInterface } from "@aws-lambda-powertools/commons/types";
import { parser } from "@aws-lambda-powertools/parser";
import {  PreTokenGenerationTriggerSchemaV2AndV3 } from "@aws-lambda-powertools/parser/schemas";

class Lambda implements LambdaInterface {
  @parser({ schema: PreTokenGenerationTriggerSchemaV2AndV3 })
  async handlerV2(
    event: PreTokenGenerationV2TriggerEvent,
    _context: Context,
  ): Promise<PreTokenGenerationV2TriggerEvent> {
    return event;
}

Steps to Reproduce

  1. Create a test using the fake event above
  2. Supply it to the empty event handler.

Possible Solution

  1. Modify the schemas for the CognitoTriggerBaseSchema as follows:

change response type from z.object({}) to z.looseObject({}) - this isn't critical as z.object({}) will strip all keys.

const CognitoTriggerBaseSchema = z.object({
  version: z.string(),
  triggerSource: z.string(),
  region: z.string(),
  userPoolId: z.string(),
  userName: z.string().optional(),
  callerContext: z.object({
    awsSdkVersion: z.string(),
    clientId: z.string(),
  }),
  request: z.object({}),
  response: z.object({}),
});
  1. Modify the PreTokenGenerationTriggerGroupConfigurationSchema to allow preferredRole to be null as follows:

change preferredRole type from z.string().optional() to z.string().nullish()

const PreTokenGenerationTriggerGroupConfigurationSchema = z.object({
  groupsToOverride: z.array(z.string()),
  iamRolesToOverride: z.array(z.string()),
  preferredRole: z.nullish(z.string()),
});

Powertools for AWS Lambda (TypeScript) version

latest

AWS Lambda function runtime

22.x

Packaging format used

npm

Execution logs

2025-08-01T15:59:10.464Z	0e1aa399-60b0-4d4b-96a8-11b480c7b536	ERROR	Invoke Error 	
{
    "errorType": "ParseError",
    "errorMessage": "Failed to parse schema",
    "name": "ParseError",
    "stack": [
        "ParseError: Failed to parse schema",
        "    at as (/var/task/dist/index.js:3:18209)",
        "    at o.value (/var/task/dist/index.js:3:18471)",
        "    at t.value (/var/task/dist/index.js:3:8914)",
        "    at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1205:29)"
    ]
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcompletedThis item is complete and has been merged/shippedgood-first-issueSomething that is suitable for those who want to start contributing

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions