Serverless Typescript: "Error: Invalid service configuration: "provider.name" property is missing"

Hello,

Event if the “provider.name” is set, I get the error “Error: Invalid service configuration: “provider.name” property is missing” when I try to deploy my stack.

import type { Serverless } from "serverless/aws";

/**
 * Authorizer with Cognito User Pool
 */
export const authorizer = {
  name: 'test-back-${sls:stage}-authorizer',
  type: 'COGNITO_USER_POOLS',
  arn: { 'Fn::GetAtt': [ 'cognitoUserPool', 'Arn' ] }
}

const serverlessConfig: Partial<Serverless> = {
  service: 'test-auth',

  provider: {
    name: "aws",
    runtime: "nodejs16.x",
    memorySize: 128,
    stage: "${opt:stage, 'dev'}",
    logRetentionInDays: 14,
    environment: {
      API_ENV: "${sls:stage}",
      NODE_OPTIONS: "--enable-source-maps",
    },
    region: "eu-west-1",
    stackTags: {
      project: "test-back",
    },

    apiName: '${opt:stage}-test-back',
    apiGateway: {
      minimumCompressionSize: 1024,
      metrics: false,
      // @ts-ignore
      restApiId: {
          Ref: 'ApiGateway',
      },
      // @ts-ignore
      restApiRootResourceId: {
        'Fn::GetAtt': ['ApiGateway', 'RootResourceId']
      },
      description: "test-back",
    },

  },
  custom: {
    esbuild: {
      bundle: true,
      // @ts-ignore
      minify: '${sls:stage}' === 'prod' ? true : false,
      packager: "pnpm",
      sourcemap: true,
      exclude: ["aws-sdk"],
    },
    apiGatewayCaching: {
      enabled: true,
    },
    "serverless-offline": {
      lambdaPort: 3000,
      httpPort: 3001,
    },
  },
  /**
   * Example functions with Cognito Authorizer
   */
  functions: {
    getHello: {
      handler: 'getHello/index.handler',
      events: [
        {
          http: {
            method: 'get',
            path: 'auth/getHello',
            authorizer: ({ 'Ref' : 'apiGatewayAuthorizer' } as unknown) as string,
            cors: true,
          },
        },
      ],
    },
  },

  resources: {
    Resources: {
      /**
      * Base Api Gateway
      */
      ApiGateway: {
        Type: 'AWS::ApiGateway::RestApi',
        Properties: {
          Name: '${opt:stage}-test-back',
        },
      },
      /**
       * Cognito - User Pool
       * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpool.html
       */
      cognitoUserPool: {
        Type: 'AWS::Cognito::UserPool',
        Properties: {
          UserPoolName: 'test-back-${sls:stage}-user-pool',
          MfaConfiguration: 'OPTIONAL',
          UsernameAttributes: [ 'email' ],
          AutoVerifiedAttributes: [ 'email' ],
          Policies: {
            PasswordPolicy: {
              MinimumLength: 8,
              RequireLowercase: true,
              RequireNumbers: true,
              RequireSymbols: true,
              RequireUppercase: true
            }
          }
        }
      },
      /**
       * Cognito - User Pool Client
       * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolclient.html
       */
      cognitoUserPoolClient: {
        Type: 'AWS::Cognito::UserPoolClient',
        Properties: {
          ClientName: 'test-back-${sls:stage}-user-pool-client',
          GenerateSecret: false,
          UserPoolId: { 'Ref': 'cognitoUserPool' },
          AccessTokenValidity: 8,
          IdTokenValidity: 8,
          RefreshTokenValidity: 7,
          TokenValidityUnits: {
            AccessToken : 'hours',
            IdToken : 'hours',
            RefreshToken : 'days'
          }, 
          ExplicitAuthFlows: [
            'ALLOW_CUSTOM_AUTH',
            'ALLOW_REFRESH_TOKEN_AUTH',
            'ALLOW_USER_SRP_AUTH' 
          ],
          EnableTokenRevocation: true,
          PreventUserExistenceErrors: 'ENABLED',
        }
      },
      /**
       * Cognito - Identity
       * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypool.html
       */
      cognitoIdentityPool: {
        Type: 'AWS::Cognito::IdentityPool',
        Properties: {
          IdentityPoolName: 'test-back-${sls:stage}-cognito-identity-pool',
          AllowUnauthenticatedIdentities: false,
          CognitoIdentityProviders: [
            {
              ClientId: { Ref: 'cognitoUserPoolClient' },
              ProviderName: { 'Fn::GetAtt': ['cognitoUserPool', 'ProviderName'] }
            }
          ]
        }
      },
      /**
       * Cognito - Base Roles: Authorized and Unauthorized
       * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypoolroleattachment.html
       */
      cognitoIdentityPoolRoles: {
        Type: 'AWS::Cognito::IdentityPoolRoleAttachment',
        Properties: {
          IdentityPoolId: { Ref: 'cognitoIdentityPool' },
          Roles: {
            authenticated: {
              'Fn::GetAtt':[ 'cognitoAuthenticatedRole', 'Arn' ]
            },
            unauthenticated: {
              'Fn::GetAtt': [ 'cognitoUnauthenticatedRole', 'Arn' ]
            }
          }
        }
      },
      /**
       * Cognito Roles
       * https://docs.aws.amazon.com/fr_fr/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html
       */
      cognitoAuthenticatedRole: {
        Type: 'AWS::IAM::Role',
        Properties: {
          RoleName: 'test-back-${sls:stage}-cognito-authorized-role',
          Path: '/',
          AssumeRolePolicyDocument: {
            Version: '2012-10-17',
            Statement: [
              {
                Effect: 'Allow',
                Principal: {
                  Federated: 'cognito-identity.amazonaws.com'
                },
                Action: [
                  'sts:AssumeRoleWithWebIdentity'
                ],
                Condition: {
                  StringEquals: {
                    'cognito-identity.amazonaws.com:aud': { 'Ref': 'cognitoIdentityPool' }
                  },
                  'ForAnyValue:StringLike': {
                    'cognito-identity.amazonaws.com:amr': 'authenticated'
                  }
                }
              }
            ]
          },
          Policies: [
            {
              PolicyName: 'test-back-${sls:stage}-cognito-authorized-policy',
              PolicyDocument: {
                Version: '2012-10-17',
                Statement: [
                  {
                    Effect: 'Allow',
                    Action: [
                      'mobileanalytics:PutEvents',
                      'cognito-sync:*',
                      'cognito-identity:*'
                    ],
                    Resource: '*'
                  },
                  {
                    Effect: 'Allow',
                    Action: [
                      'execute-api:Invoke'
                    ],
                    Resource: '*' // @TOUP: better security to change to API / lambda that request need to access
                  }
                ]
              }
            }
          ]
        }
      },
      cognitoUnauthenticatedRole: {
        Type: 'AWS::IAM::Role',
        Properties: {
          RoleName: 'test-back-${sls:stage}-cognito-unauthorized-role',
          Path: '/',
          AssumeRolePolicyDocument: {
            Version: '2012-10-17',
            Statement: [
              {
                Effect: 'Allow',
                Principal: {
                  Federated: 'cognito-identity.amazonaws.com'
                },
                Action: [
                  'sts:AssumeRoleWithWebIdentity'
                ],
                Condition: {
                  'StringEquals': {
                    'cognito-identity.amazonaws.com:aud': { 'Ref': 'cognitoIdentityPool' }
                  },
                  'ForAnyValue:StringLike': {
                    'cognito-identity.amazonaws.com:amr': 'unauthenticated'
                  }
                }
              }
            ]
          },
          Policies: [
            {
              PolicyName: 'test-back-${sls:stage}-cognito-unauthorized-policy',
              PolicyDocument: {
                Version: '2012-10-17',
                Statement: [
                  {
                    Effect: 'Allow',
                    Action: [
                      'mobileanalytics:PutEvents',
                      'cognito-sync:*',
                      'cognito-identity:*'
                    ],
                    Resource: '*'
                  }
                ]
              }
            }
          ]
        }
      },
      /**
       * API Gateway
       * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-authorizer.html
       */
      apiGatewayAuthorizer: {
        Type: 'AWS::ApiGateway::Authorizer',
        Properties: {
          name: 'test-back-${sls:stage}-authorizer',
          type: 'COGNITO_USER_POOLS',
          IdentitySource: 'method.request.header.Authorization',
          // IdentityValidationExpression: Bearer (.*) // reject mal formated Authorization header
          // AuthorizerResultTtlInSeconds: // change default 300 TTL cache settings
          ProviderARNs: [
            { 'Ref': 'cognitoUserPool' }
          ],
          RestApiId: {
            'Fn::ImportValue': '${opt:stage}-ApiGateway-restApiId'
          }
        }
      }
    },
    Outputs: {
      apiGatewayAuthorizerId: {
        Value: {
          Ref: 'apiGatewayAuthorizer',
        },
        Export: {
          Name: '${opt:stage}-ApiGateway-AuthorizerId',
        },
      },
    },
  }
};

module.exports = {serverlessConfig, authorizer};


Environment:

  • darwin,
  • node 16.17.0,
  • framework 3.22.0 (local) 3.22.0v (global),
  • plugin 6.2.2,
  • SDK 4.3.2

I exported in environment variable “SLS_DEBUG=*” and adding option --verbose at my sls command, I still get the generic error without any log:

after too much time, I found my error: updated the module.exports value:

module.exports =  { serverlessConfig, authorizer };

to

module.exports = serverlessConfig, { authorizer };