aws-lambdalambdaserverlessaws-serverlessserverless-offline

Serverless Offline - Attempt to invoke function 'xxx' failed. Function does not exists


Hello :) Hope to find you well.

I am trying to set test my serverless environment locally via the serverless-offline node package.

Here is my serverless.yml file:

org: etisreal11
app: leaderboards-api
service: leaderboards-api

provider:
  name: aws
  runtime: nodejs18.x
  stage: STG
  profile: local
  region: eu-central-1
  environment:
    TABLE_NAME: ${self:custom.TABLE_NAME}
    DYNAMODB_HOSTNAME: localhost
    AWS_ACCESS_KEY: Local
    AWS_SECRET_KEY: Local
  logs:
    httpApi: true


custom:
  serverless-offline:
    noPrependStageInUrl: true
    resourceRoutes: true # HTTP Proxy
  TABLE_NAME: ${self:provider.stage}_Leaderboards

plugins:
  - serverless-dynamodb-local
  - serverless-offline
  - serverless-offline-lambda

package:
  individually: true

functions:
  adminHandler:
    handler: adminHandler/leaderboardsAdminHandler.handler
    environment:
      TABLE_NAME: ${self:custom.TABLE_NAME}
      DYNAMODB_HOSTNAME: ${self:provider.environment.DYNAMODB_HOSTNAME}
    events:
      - http:
          path: /
          method: ANY
      - http:
          path: '{proxy+}'
          method: ANY

resources:
  Resources:
    STGLeaderboards:
      Type: AWS::DynamoDB::Table
      Properties:
        TABLE_NAME: ${self:custom.TABLE_NAME}
        AttributeDefinitions:
          - AttributeName: PK
            AttributeType: S
          - AttributeName: SK
            AttributeType: S
        KeySchema:
          - AttributeName: PK
            KeyType: HASH
          - AttributeName: SK
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST

This is the file I am referencing:

export const handler = async (event) => {

    switch (event.routeKey) {
        case 'POST /admin/leaderboard':
        try {
            const validatedResponse = returnCreateLeaderboardReq(JSON.parse(event.body))

            // Invalid payload
            if (validatedResponse?.statusCode === 422) return JSON.stringify(validatedResponse)
            
            const createdLeadRes = await documentClient.send(new PutCommand(validatedResponse))
            
            return JSON.stringify({
                statusCode: 201,
                body: { message: createdLeadRes }
            })
        } catch (error) {
     ...

and this is the output of the tree command: tree -L 2

.
├── adminHandler
│   └── leaderboardsAdminHandler.js
├── convert-to-base64.js
├── create-dynamodbtable.md
├── docker
│   └── dynamodb
├── docker-compose.yaml
├── index.js
├── leaderboardsStreamHandler
│   ├── deleteHandler.js
│   ├── deleteHandler.test.js
│   ├── insertHandler.js
│   ├── insertHandler.test.js
│   ├── leaderboardsStreamHandler.js
│   ├── leaderboardsStreamHandler.test.js
│   ├── utils.js
│   └── utils.test.js
├── mock-data
│   ├── encoded-lighter-create
│   ├── encoded-lighter-remove
│   ├── encoded-single-tournament
│   ├── participants.json
│   ├── single-tournament.json
│   ├── single-tournament.zip
│   ├── tournaments.json
│   ├── tournaments-lighter.json
│   ├── tournaments-lighter-remove.json
│   ├── tournaments-lighter-remove.zip
│   ├── tournaments-lighter.zip
│   ├── tournaments-light.json
│   ├── tournaments-light.zip
│   └── tournaments.zip
├── node_modules
|
├── offline
│   └── migrations
├── OLD-leaderboardsStreamHandler
│   ├── insertHandler.js
│   ├── leaderboardsStreamHandler.js
│   ├── modifyHandler.js
│   └── NOTES.md
├── package.json
├── package-lock.json
├── README.md
├── serverless.yml
└── vitest.config.ts

Everything starts up correctly:

Starting Offline at stage STG (eu-central-1)

Offline Lambda Server listening on http://localhost:4000
Offline [http for lambda] listening on http://localhost:3002
Function names exposed for local invocation by aws-sdk:
           * adminHandler: leaderboards-api-STG-adminHandler

   ┌────────────────────────────────────────────────────────────────────────────────┐
   │                                                                                │
   │   ANY | http://localhost:3000/                                                 │
   │   POST | http://localhost:3000/2015-03-31/functions/adminHandler/invocations   │
   │   ANY | http://localhost:3000/{proxy*}                                         │
   │   POST | http://localhost:3000/2015-03-31/functions/adminHandler/invocations   │
   │                                                                                │
   └────────────────────────────────────────────────────────────────────────────────┘

Server ready: http://localhost:3000 🚀

however, if I try to get any of the endpoints above (or any other) I get this error:

✖ Attempt to invoke function 'adminHandler' failed. Function does not exists.

I've looked into these questions:

"Serverless-offline: route not found." running an AWS Lambda function in offline mode

Serverless Offline: Error while running handler, cannot find module

but I wasn't able to solve it after far too many hours. Honestly, I have no clue of what is going on. I wish I could provide more insight :/

If you have any suggestion of tip, it would be very much appreciated...

Thanks in advance


Solution

  • Remove the serverless-offline-lambda serverless plugin from serverless.yml file:

    plugins:
      - serverless-dynamodb-local
      - serverless-offline
      - serverless-offline-lambda
    

    For one, you just need serverless-offline plugin to run lambda in your local now.

    Second, serverless-offline-lambda plugin was last updated over 4 years back. Both serverless and serverless-offline had changed a lot within these years.