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

Created on 1 Sep 2017  路  19Comments  路  Source: aws/serverless-application-model

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
aredocs areexamples contributorgood-first-issue good first issue typdocumentation

Most helpful comment

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.

All 19 comments

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.

This might be a documentation issue. We are using a standard mechanism for constructing resource names. You should be able to use "DependsOn" to chain the resource creation in correct order. I will update the docs to explain how the resource names are created.

I really don't understand why it's trying to redeploy my API gateway stages in the first place. If my function that an API gateway resource is using is pointing to ":Latest" then why do we need to redeploy?

I'm having similar issue.

I tried using DependsOn to specify that the BasePathMapping depends on my AWS::ApiGateway::DomainName and AWS::Serverless::Api resource, but it is still created before Stage is created. I'm guessing that's because Stage is a separate resource outside of AWS::Serverless::Api.

Thanks to @jvanbrunschot-coolblue 's comment, I was able to find a workaround. It looks like ServerlessApiStage is indeed a separate resource outside of AWS::Serverless::Api, and is generated by the transform function. So my workaround is to figure out what the generated resource name would be for the stage and specify that in the DependsOn section of the AWS::ApiGateway::BasePathMapping resource.

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

Hi,
I had to add apiStage and not only Stage.

aws-cli/1.15.66
SAM CLI, version 0.5.0

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

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

Having Domain and Certificate parameters makes sense to me. If Certificate is not passed AWS::Serverless::API could create AWS::CertificateManager::Certificate resource too.

Any update on this? Would great to make this easier. Ran into this problem again recently.
If need to understand the inner of an abstraction (i.e SAM) in order to use it then surely it's not doing its job?

I added an RFC for this here https://github.com/awslabs/serverless-application-model/issues/783. I'm going to close out this issue as a workaround has been posted, and we have a path forward to a simpler solution.

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

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 Thanks for the comment! This will be a really good addition to the examples folder. Reopening this issue.

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!

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
Use "!Ref Api.Stage" as reference works here!!
Thanks!!!

it works perfect for me
Use "!Ref Api.Stage"

Was this page helpful?
0 / 5 - 0 ratings

Related issues

voigt picture voigt  路  3Comments

feinstein picture feinstein  路  3Comments

vinkris picture vinkris  路  3Comments

willdady picture willdady  路  3Comments

kwcrook picture kwcrook  路  3Comments