anomalyco/sst · error · VisibleError

You cannot set both aliases and usernames. Learn more about

Error message

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

What it means

In Cognito, a user pool uses either alias attributes (email/phone/preferred_username re-assignable identifiers) or explicit username attributes — not both. SST surfaces this Cognito constraint as a VisibleError when both args.aliases and args.usernames are set.

Source

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

    const userPool = createUserPool();

    const domain = normalizeDomain();
    const certificateArn = createSsl();
    const cognitoDomain = createCognitoDomain();
    createDnsRecords();

    this.constructorOpts = opts;
    this.userPool = userPool;
    this._domainUrl = domain?.apply((d) =>
      d.prefix
        ? interpolate`https://${d.prefix}.auth.${region}.amazoncognito.com`
        : interpolate`https://${d.name}`,
    );

    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 {

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Remove args.usernames and keep args.aliases (recommended for flexible sign-in identifiers).
  2. Or remove args.aliases if you specifically need fixed username attributes.
  3. Decide based on sign-in model: aliases allow multiple identifiers per user; usernames are immutable.
  4. Note this cannot be changed after a pool is created — plan before first deploy.

Example fix

// before
new sst.aws.CognitoUserPool('MyPool', {
  aliases: ['email', 'preferred_username'],
  usernames: ['email']
});
// after
new sst.aws.CognitoUserPool('MyPool', {
  aliases: ['email', 'preferred_username']
});
Defensive patterns

Strategy: validation

Validate before calling

function validateUserPoolIdentity(poolArgs) {
  if (poolArgs.aliases && poolArgs.usernames)
    throw new Error('Choose either aliases or usernames, not both');
}
validateUserPoolIdentity({ aliases: ['email'] });

Prevention

When it happens

Trigger: new sst.aws.CognitoUserPool('X', { aliases: [...], usernames: [...] }) — normalizeAliasesAndUsernames applies both args and throws when both are truthy.

Common situations: Extending an existing pool config that used usernames by also adding aliases for social sign-in; merging configs from two examples; misunderstanding Cognito's alias-vs-username semantics.

Related errors


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