serverless-application-model: BasePathMapping deployment error: Invalid stage identifier specified

I have a SAM template deploying three resources: An ApiGateway, a Lambda Function and a ApiGateway BasePathMapping.

    AWSTemplateFormatVersion: '2010-09-09'
    Transform: AWS::Serverless-2016-10-31
    Parameters:
      StageName:
        Type: String
    Resources:
      api:
        Type: AWS::Serverless::Api
        Properties:
          DefinitionBody: ...
          StageName: !Ref StageName
      apidomain:
        Type: AWS::ApiGateway::BasePathMapping
        Properties:
          DomainName: mydomain.com
          RestApiId: !Ref api
          Stage: !Ref StageName
      lambda:
        Type: AWS::Serverless::Function
        Properties: ...

There is one parameter to the template called StageName, and this is used in two places:

  1. The StageName for the ApiGateway
  2. The Stage value for the BasePathMapping

When this stack is deployed, Cloud Formation deploys things in a strange order. It deploys the Api Gateway before the BasePathMapping, which you would expect, but deploying the ApiGateway stage is a separate step. It tries to deploy the BasePathMapping before the ApiGateway Stage, which results in the error:

Invalid stage identifier specified

This is totally underdtandable given it has not been created yet.

I have tried using the DependsOn property on the BasePathMapping resource to force it to get created after the ApiGateway. It does, but not after the ApiGateway stage.

Does anyone know a way around this? It feels like a bug with the AWS::Serverless::Api resource type. It clearly needs to create a Gateway and a Stage, but the should be done sequentially not not allow the BasePathMapping to be created in between.

Work arounds I don’t like include:

  1. A two stage deployment. First without the BasePathMapping, then with it

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 5
  • Comments: 30 (4 by maintainers)

Commits related to this issue

Most upvoted comments

For me the solution was:

Resources:
  Api:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        DefaultAuthorizer: NONE
  BasePathMapping:
    Type: AWS::ApiGateway::BasePathMapping
    Properties:
      DomainName: !Ref GatewayDomain
      RestApiId: !Ref Api
      Stage: !Ref Api.Stage

Notice the BasePathMapping.Stage is set to !Ref Api.Stage which creates tight coupling and removes potential user errors such as typos.

@ca0abinary Use “!Ref Api.Stage” as reference works here!! Thanks!!!

Indeed it seems to be a bug, which disregards the dependencies between these resources. I am using SAM CLI 0.4.0 and AWS CLI 1.11.131 and had the same problem. In my case the final template generate by Cloudformation produced the stage name as a concatenation of my API logical name and word Stage: <myApiLogicalName>Stage.

Fixed the problem by adding a DependsOn on AWS::ApiGateway::BasePathMapping as seen below:

  # ########################################################################
  # Mobile API
  apiMobile:
    Type: 'AWS::Serverless::Api'
    Properties:
      Name: mobile-api
      StageName: !FindInMap [ApiStage, !Ref Environment, stage]
      DefinitionBody:
        'Fn::Transform':
          Name: 'AWS::Include'
          Parameters:
            Location: 's3://<redacted>/swagger.yaml'
      EndpointConfiguration: REGIONAL

  # ###################################################################
  # Base Path Mapping
  apiBasePathMapping:
    Type: 'AWS::ApiGateway::BasePathMapping'
    Properties:
      BasePath: v1.0
      Stage: !FindInMap [ApiStage, !Ref Environment, stage]
      DomainName:
        'Fn::Sub':
          - 'mobile-api${Suffix}.<redacted>'
          - Suffix: !FindInMap
            - EnvironmentShort
            - !Ref Environment
            - suffix
      RestApiId: !Ref apiMobile
    DependsOn:
      - apiMobileStage  <------ Added explicit dependency

it works perfect for me Use “!Ref Api.Stage”

Indeed it seems to be a bug, which disregards the dependencies between these resources. I am using SAM CLI 0.4.0 and AWS CLI 1.11.131 and had the same problem. In my case the final template generate by Cloudformation produced the stage name as a concatenation of my API logical name and word Stage: <myApiLogicalName>Stage. Fixed the problem by adding a DependsOn on AWS::ApiGateway::BasePathMapping as seen below:

  # ########################################################################
  # Mobile API
  apiMobile:
    Type: 'AWS::Serverless::Api'
    Properties:
      Name: mobile-api
      StageName: !FindInMap [ApiStage, !Ref Environment, stage]
      DefinitionBody:
        'Fn::Transform':
          Name: 'AWS::Include'
          Parameters:
            Location: 's3://<redacted>/swagger.yaml'
      EndpointConfiguration: REGIONAL

  # ###################################################################
  # Base Path Mapping
  apiBasePathMapping:
    Type: 'AWS::ApiGateway::BasePathMapping'
    Properties:
      BasePath: v1.0
      Stage: !FindInMap [ApiStage, !Ref Environment, stage]
      DomainName:
        'Fn::Sub':
          - 'mobile-api${Suffix}.<redacted>'
          - Suffix: !FindInMap
            - EnvironmentShort
            - !Ref Environment
            - suffix
      RestApiId: !Ref apiMobile
    DependsOn:
      - apiMobileStage  <------ Added explicit dependency

THIS IS IT THANKS FOR TAKING ME OUT OF MY DESPERATION PIT

Thank you it worked for me SAM 0.22.0 I had the same issue: just refer the object with the same name plus stage. To verify you are referring the right resources compiled by sam, I suggest to run sam validate --debug and verify the name 😃 thank you again!

Adding a DomainName property to the AWS::Serverless::API resources which configures this all for you is probably what we want here.

I got a workaround for this… Apparently when using SAM (aws cloudformation deploy) it uses the transform (Transform: AWS::Serverless-2016-10-31) rule set in your template to generate all kind of “extra” resources. One of them is a aws::ApiGateway::stage resource. The name of this resource is ServerlessApiStage where ServerlessApi is the name of the AWS::Serverless::Api resource.

Based on the link below this should have been fixed by adding a DependsOn to <api‑LogicalId><stage‑name>Stage (as documented in this link: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-generated-resources-api.html)

Template format error: Unresolved resource dependencies [RestAPIGatewaydevelopmentStage] in the Resources block of the template

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Parameters:
  APIStageName:
    Type: 'AWS::SSM::Parameter::Value<String>'
    Description: The name of the stage to deploy the API to.
    Default: /account/environment
Resources:    
  RestAPIGateway:
    Type: AWS::ApiGateway::RestApi
...
  APICustomDomainMapping:
    Type: AWS::ApiGateway::BasePathMapping
    DependsOn: 
     - RestAPIGatewaydevelopmentStage
    Properties:
      DomainName: !Ref APICustomDomain
      RestApiId: !Ref RestAPIGateway
      Stage: !Ref APIStageName

It is hard to believe that this issue has not been addressed after almost 5 years. It seems that adding an explicit dependson on the stage generated during translation should fix this.

Indeed it seems to be a bug, which disregards the dependencies between these resources. I am using SAM CLI 0.4.0 and AWS CLI 1.11.131 and had the same problem. In my case the final template generate by Cloudformation produced the stage name as a concatenation of my API logical name and word Stage: <myApiLogicalName>Stage.

Fixed the problem by adding a DependsOn on AWS::ApiGateway::BasePathMapping as seen below:

  # ########################################################################
  # Mobile API
  apiMobile:
    Type: 'AWS::Serverless::Api'
    Properties:
      Name: mobile-api
      StageName: !FindInMap [ApiStage, !Ref Environment, stage]
      DefinitionBody:
        'Fn::Transform':
          Name: 'AWS::Include'
          Parameters:
            Location: 's3://<redacted>/swagger.yaml'
      EndpointConfiguration: REGIONAL

  # ###################################################################
  # Base Path Mapping
  apiBasePathMapping:
    Type: 'AWS::ApiGateway::BasePathMapping'
    Properties:
      BasePath: v1.0
      Stage: !FindInMap [ApiStage, !Ref Environment, stage]
      DomainName:
        'Fn::Sub':
          - 'mobile-api${Suffix}.<redacted>'
          - Suffix: !FindInMap
            - EnvironmentShort
            - !Ref Environment
            - suffix
      RestApiId: !Ref apiMobile
    DependsOn:
      - apiMobileStage  <------ Added explicit dependency

THIS IS IT THANKS FOR TAKING ME OUT OF MY DESPERATION PIT

Hi, So i was stuck in the same scenario and after a lot of help from the above comments and a little trial and error on my end. The format of the aws::ApiGateway::stage is => (name of the serverless api resource)(stage name)Stage

If anyone is using an Http protocol API and the AWS::ApiGatewayV2:ApiMapping I solved this by referencing ServerlessHttpApiApiGatewayDefaultStage for stage.

  ApiMapping:
    Type: AWS::ApiGatewayV2::ApiMapping
    Properties:
      ApiId: !Ref ServerlessHttpApi
      DomainName: !Ref ApiDomainName
      Stage: !Ref ServerlessHttpApiApiGatewayDefaultStage

@ca0abinary Thanks for the comment! This will be a really good addition to the examples folder. Reopening this issue.