serverless: Request Validator name must be unique

Are you certain it’s a bug?

  • Yes, it looks like a bug

Is the issue caused by a plugin?

  • It is not a plugin issue

Are you using the latest version?

  • Yes, I’m using the latest version

Is there an existing issue for this?

  • I have searched existing issues, it hasn’t been reported yet

Issue description

I started to see this error in our production build when updating from v2.47.0 to v2.61.0 (since also tried v2.62.0)

Serverless Error ----------------------------------------

 An error occurred: ApiGatewayBcbserverapiRequestValidator - Resource handler returned message: "Request Validator name must be unique (Service: ApiGateway, Status Code: 400, Request ID: 30e29e25-296a-42c0-8e6d-cc8a6f31b826, Extended Request ID: null)" (RequestToken: f3479759-3512-b778-ed37-ea6faf4034d5, HandlerErrorCode: AlreadyExists).

Somehow it tries to create a RequestValidator that already exists. I can get the deploy to work when I rename the validator just before I deploy using aws apigateway update-request-validator --rest-api-id {apiID} --request-validator-id {validatorId} --patch-operations op=replace,path=/name,value=some-other-name

Is there a way to turn off the request validators? I don’t really need those and have no idea why they’re turned on here but not on some of my other APIs

Service configuration (serverless.yml) content

service: bcb-server-api

frameworkVersion: "=2.62.0"

projectDir: ../../

plugins:
  - serverless-iam-roles-per-function
  - serverless-domain-manager
  - serverless-prune-plugin
  - serverless-associate-waf
  - serverless-offline

provider:
  name: aws
  runtime: nodejs14.x
  region: us-east-1
  stage: ${self:custom.stage}
  deploymentBucket:
    name: ${self:custom.config.deploymentBucket}
    serverSideEncryption: AES256
  environment: ${file(./environment.yaml)}

  apiGateway:
    apiKeySourceType: AUTHORIZER
    minimumCompressionSize: 1024
  endpointType: REGIONAL
  logRetentionInDays: 90
  tracing:
    apiGateway: true
    lambda: true
  tags:
    WAFCustomHeader: true

  vpc:
    securityGroupIds:
      - ${self:custom.config.noIngressSecurityGroup}
    subnetIds: ${self:custom.config.privateSubnetIds}
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - xray:PutTraceSegments
            - xray:PutTelemetryRecords
          Resource: "*"

custom:
  stage: ${opt:stage, 'local'}
  serverless-offline:
    httpPort: 8100
    lambdaPort: 18100
    noPrependStageInUrl: true

  prune:
    automatic: true
    number: 5

  serverless-iam-roles-per-function:
    defaultInherit: true

  associateWaf:
    version: V2
    name: ${self:custom.config.WAFname}

  # stage dependent variables
  config: ${file(./env-${self:custom.stage}.yml)}

  customDomain:
    enabled: ${self:custom.config.domainManagerEnabled}
    domainName: api.${self:custom.config.baseDomain}
    basePath: api
    createRoute53Record: true
    endpointType: regional
    securityPolicy: tls_1_2

functions:
  ProxyFunction:
    handler: index.handler
    memorySize: 1792
    timeout: 10
    iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:Query
        Resource:
          - ${self:provider.environment.DYNAMODB_TABLE_MAIN_ARN}

    events: ${file(./serverless-bcb-api-events.json)}
    onError: arn:aws:sns:${self:provider.region}:${self:custom.config.accountId}:pager-topic

  AuthFunction:
    handler: ./auth.handler
    memorySize: 512
    iamRoleStatements:
      - Effect: Allow
        Action:
          - dynamodb:Query
        Resource:
          - ${self:provider.environment.DYNAMODB_TABLE_MAIN_ARN}

resources:
  Outputs:
    ApiId:
      Description: ID of the API
      Value: !Ref ApiGatewayRestApi
      Export:
        Name: api-id

Command name and used flags

sls deploy --verbose

Command output

NA

Environment information

Operating System:          linux
    Node Version:              14.17.2
    Framework Version:         2.62.0 (local)
    Plugin Version:            5.4.7
    SDK Version:               4.3.0
    Components Version:        3.17.1

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 7
  • Comments: 33 (18 by maintainers)

Most upvoted comments

Thanks for clarification @necojackarc - that definitely sounds like something funky was happening under the AWS hood during these deployments. If any of you experience more issues like this, please report it here so we will be able to nail down the potential cause in Framework 👍

I saw the same issue today having upgraded from serverless v1 to v2.66.1 - 2 of my stages deployed fine from packages, one failed with the above error.

Following the suggestion of @necojackarc, I removed the validator and sls deployed, then all was well. I didn’t wait between removal and re-deploy: aws apigateway get-request-validators --rest-api-id XXX aws apigateway delete-request-validator --rest-api-id XXX --request-validator-id XXX

Thanks to @jon-flowers we followed his advice and it worked out, just fyi to get the list of validators I used this CLI

aws apigateway get-request-validators --rest-api-id XXXX

{
    "items": [
        {
            "id": "YYYY",
            "name": "serverless-api-dev | Validate request body and querystring parameters",
            "validateRequestBody": true,
            "validateRequestParameters": true
        }
    ]
}

then, you will see the list and use the ID to delete it

aws apigateway delete-request-validator --rest-api-id XXXX --request-validator-id YYYY

Hello @igoralves1, thanks for bringing this up - in your situation you can use --force flag to force the deployment.

  • Check if there’s the validator created (aws apigateway get-request-validators --rest-api-id XXX)
  • Delete the validator (aws apigateway delete-request-validator --rest-api-id XXX --request-validator-id XXX)
  • Wait for a couple of hours
  • Redeploy

🤯

I hit this repeatedly today in one of my serverless applications that has been around for a couple years. It generally appears that for some reason Serverless “loses track” of its previously deployed RequestValidator (notably, it’s not any one that will be defined in the serverless.yaml, but the “under the hood” one it creates itself). It then fails to deploy because it tries to create a new one that has the exact same name as the one that already exists.

This solution worked for me; reposting because it didn’t have many reactions and it’s clear many people are hitting this problem. If you use the CLI to delete the existing validator and then run a deployment again, it should work. As mentioned above, you have to delete the one that serverless creates automatically; for instance, I had two validators. One specifically created in my YAML, the other with the name “$service-$stage | Validate request body and querystring parameters”. I had to delete the latter with the CLI for my deployment to work

What I don’t know yet is if I will hit this problem again on my next deploy / update, but if I do I will let you know.

I saw a similar issue today. When I deployed to production, I got the same error but I didn’t when I deployed to testing. I mean, I deployed the same code into two stages, then one worked, but the other didn’t.

It seemed like Cloudformation created the validator, tried to create the same one again, then failed with the error. It also failed to roll back, so I needed to manually delete the validator (N.B. this was our first deployment with a newer version of Serverless, so we didn’t have the validator till today).

Subsequently, I started seeing "Too Many Requests (Service: ApiGateway, Status Code: 429, Request ID: XXX, Extended Request ID: null)" on that stage while I managed to deploy to the other stage…, so I decided to just leave it for a while. I felt Cloudformation was working a bit weirdly today.

I just deployed to the stage again, then it worked…!

I don’t know if you are in the same situation but what I did is basically,

  • Check if there’s the validator created (aws apigateway get-request-validators --rest-api-id XXX)
  • Delete the validator (aws apigateway delete-request-validator --rest-api-id XXX --request-validator-id XXX)
  • Wait for a couple of hours
  • Redeploy

🤯