anomalyco/sst · error · VisibleError

You must provide a KMS key via `kmsKey` when configuring `cu

Error message

You must provide a KMS key via `kmsKey` when configuring `customEmailSender` or `customSmsSender`.

What it means

Cognito's customEmailSender and customSmsSender Lambda triggers encrypt the message code with a dedicated KMS key. AWS requires this key, so SST throws a VisibleError if either trigger is configured without args.triggers.kmsKey.

Source

Thrown at platform/src/components/aws/cognito-user-pool.ts:644

    function normalizeAliasesAndUsernames() {
      all([args.aliases, args.usernames]).apply(([aliases, usernames]) => {
        if (aliases && usernames)
          throw new VisibleError(
            "You cannot set both aliases and usernames. Learn more about customizing sign-in attributes at https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-aliases",
          );
      });
    }

    function normalizeTriggers() {
      if (!args.triggers) return;

      return output(args.triggers).apply((triggers) => {
        if (
          (triggers.customEmailSender || triggers.customSmsSender) &&
          !triggers.kmsKey
        )
          throw new VisibleError(
            "You must provide a KMS key via `kmsKey` when configuring `customEmailSender` or `customSmsSender`.",
          );

        return {
          ...triggers,
          preTokenGenerationVersion:
            triggers.preTokenGenerationVersion === "v2" ? "V2_0" : "V1_0",
        };
      });
    }

    function normalizeVerify() {
      if (!args.verify) return;

      return output(args.verify).apply((verify) => {
        return {
          defaultEmailOption: "CONFIRM_WITH_CODE",
          emailMessage:

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Create a KMS key and pass it via triggers.kmsKey.
  2. Grant the Cognito service principal and the sender Lambda access to the key.
  3. Or remove customEmailSender/customSmsSender and use Cognito's built-in email/SMS sending if custom encryption isn't needed.

Example fix

// before
triggers: { customEmailSender: { function: senderFn } }
// after
const key = new sst.aws.KmsKey('SenderKey');
triggers: { customEmailSender: { function: senderFn }, kmsKey: key }
Defensive patterns

Strategy: validation

Validate before calling

function validateTriggers(triggers) {
  if ((triggers?.customEmailSender || triggers?.customSmsSender) && !triggers?.kmsKey)
    throw new Error('triggers.kmsKey is required with customEmailSender/customSmsSender');
}
validateTriggers(triggersConfig);

Prevention

When it happens

Trigger: new sst.aws.CognitoUserPool('X', { triggers: { customEmailSender: {...}, customSmsSender: {...} } }) with no kmsKey in triggers — checked in normalizeTriggers.

Common situations: Adding a custom sender function following a tutorial that omitted the KMS requirement; migrating from Lambda email config to custom senders and not creating a key.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/7d16037722ad9a88. Report an issue: GitHub.