dherault / serverless-offline

Emulate AWS λ and API Gateway locally when developing your Serverless project
MIT License
5.19k stars 795 forks source link

local invokes to 'http for lambda' throw an error (Python 3.8 runtime) #969

Closed rbuckingham closed 2 years ago

rbuckingham commented 4 years ago

Bug Report

Current Behavior Calls to the http for lambda listener do not work as expected and throw an error in the destination function as seen in the terminal:

offline: Offline [http for lambda] listening on http://localhost:5005

   ┌───────────────────────────────────────────────────────────────────────────┐
   │                                                                           │
   │   GET | http://localhost:3005/local/orgs/{id}                             │
   │   POST | http://localhost:3005/2015-03-31/functions/readOrg/invocations   │
   │                                                                           │
   └───────────────────────────────────────────────────────────────────────────┘

offline: [HTTP] server ready: http://localhost:3005 🚀
offline:
offline: Enter "rp" to replay the last request
Debug: internal, implementation, error
    TypeError: Cannot destructure property `handler` of 'undefined' or 'null'.
    at new LambdaFunction (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/serverless-offline/dist/lambda/LambdaFunction.js:107:9)
    at LambdaFunctionPool.get (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/serverless-offline/dist/lambda/LambdaFunctionPool.js:94:24)
    at Lambda.get (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/serverless-offline/dist/lambda/Lambda.js:60:88)
    at Lambda.getByFunctionName (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/serverless-offline/dist/lambda/Lambda.js:66:17)
    at InvocationsController.invoke (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/serverless-offline/dist/lambda/routes/invocations/InvocationsController.js:24:80)
    at handler (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/serverless-offline/dist/lambda/routes/invocations/invocationsRoute.js:49:36)
    at module.exports.internals.Manager.execute (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/@hapi/hapi/lib/toolkit.js:41:33)
    at Object.internals.handler (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/Users/richard/Documents/projects/dotOrg/services/ns-read-org/node_modules/@hapi/hapi/lib/request.js:312:68)
    at process._tickCallback (internal/process/next_tick.js:68:7)

This is confirmed by the response (as seen by curl/postman) when sent the most basic post request:

post: {"test":"test"}
response:
{
    "statusCode": 500,
    "error": "Internal Server Error",
    "message": "An internal server error occurred"
}

If invoked directly via a POST to http://localhost:5005/2015-03-31/functions/readOrg/invocations you get the exact same error (confirming the issue is not source function code related.)

Sample Code

service: ns-read-org
app: services
org: myorg

provider:
  name: aws
  runtime: python3.8
  stage: ${opt:stage, 'local'}
  log: ${opt:log, 'info'}
  region: us-west-2
  stackName: ${self:service}-${opt:developer, self:provider.stage}

functions:
  readOrg: 
    handler: src/readOrg.handler
    events:
      - httpApi: GET /orgs/{id}
def handler(request, context):
    print("hello world")

Environment

Possible Solution No known workarounds.

4lph4-Ph4un commented 4 years ago

I have a similar issue, but with node 12.16.3-runtime and a codebase written in TypeScript. serverless-offline is of matching version while serverless is 1.69.0.

Debug: internal, implementation, error 
    TypeError: Cannot destructure property 'handler' of 'functionDefinition' as it is undefined.
    at new LambdaFunction (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/serverless-offline/dist/lambda/LambdaFunction.js:105:7)
    at LambdaFunctionPool.get (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/serverless-offline/dist/lambda/LambdaFunctionPool.js:94:24)  
    at Lambda.get (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/serverless-offline/dist/lambda/Lambda.js:60:88)
    at Lambda.getByFunctionName (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/serverless-offline/dist/lambda/Lambda.js:66:17)
    at InvocationsController.invoke (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/serverless-offline/dist/lambda/routes/invocations/InvocationsController.js:24:80)
    at handler (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/serverless-offline/dist/lambda/routes/invocations/invocationsRoute.js:49:36)    at module.exports.internals.Manager.execute (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/@hapi/hapi/lib/toolkit.js:41:33)
    at Object.internals.handler (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/@hapi/hapi/lib/request.js:312:68)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)     
    at Request._execute (/d/Projects/JavaScript/ElasticSearch/RecipeAPI/node_modules/@hapi/hapi/lib/request.js:221:9)

This is happens after calling invoke for aws-sdk-Lambda:

import { Lambda } from "aws-sdk";

const LAMBDA = new Lambda({
  apiVersion: "2015-03-31",
  endpoint:   process.env.LAMBDA_ENDPOINT
});

export const recurse = async (payload, ctx) => {
  const resp = await LAMBDA.invoke({ 
    FunctionName:   ctx.functionName,
    InvocationType: "Event",
    Payload:        JSON.stringify(payload)
  }).promise();
  return resp;
};

I wonder if we are looking at the same issue, but from a different angle?

phmasek commented 4 years ago

Having the same issue as @4lph4-Ph4un.

serverless.yml config:

service: service-name

provider:
  name: aws
  runtime: nodejs10.x
  stage: ${opt:stage,'dev'}
  region: eu-north-1

functions:
  functionName:
    handler: functions.functionName
    events:
      - http:
          path: function/{id}
          method: post
          request:
            parameters:
              paths:
                id: true
      - schedule: 
          rate: cron(0 7-20 ? * MON-FRI *)
          enabled: false

package:
  include:
    - ../node_modules/**
  excludeDevDependencies: false

Invoke code:

const { Lambda } = require('aws-sdk');

module.exports.create = async (event, context, callback) => {
  const lambdaConfig = {
    apiVersion: '2015-03-31',
  };

  if (process.env.IS_LOCAL == 'true') {
    lambdaConfig.endpoint = 'http://localhost:3002';
  }

  const lambda = new Lambda(lambdaConfig);
  const opts = {
    FunctionName: 'service-name-functionName',
    InvocationType: 'RequestResponse',
  };

  lambda.invoke(opts, (err, res) => {
    console.log(err);
  });
}

Output in sls offline terminal:

Debug: internal, implementation, error
    TypeError: Cannot destructure property 'handler' of 'functionDefinition' as it is undefined.
    at new LambdaFunction (/project/node_modules/serverless-offline/dist/lambda/LambdaFunction.js:133:7)
    at LambdaFunctionPool.get (/project/node_modules/serverless-offline/dist/lambda/LambdaFunctionPool.js:93:24)
    at Lambda.get (/project/node_modules/serverless-offline/dist/lambda/Lambda.js:60:88)
    at Lambda.getByFunctionName (/project/node_modules/serverless-offline/dist/lambda/Lambda.js:66:17)
    at InvocationsController.invoke (/project/node_modules/serverless-offline/dist/lambda/routes/invocations/InvocationsController.js:24:80)
    at handler (/project/node_modules/serverless-offline/dist/lambda/routes/invocations/invocationsRoute.js:49:36)
    at module.exports.internals.Manager.execute (/project/node_modules/@hapi/hapi/lib/toolkit.js:41:33)
    at Object.internals.handler (/project/node_modules/@hapi/hapi/lib/handler.js:46:48)
    at exports.execute (/project/node_modules/@hapi/hapi/lib/handler.js:31:36)
    at Request._lifecycle (/project/node_modules/@hapi/hapi/lib/request.js:312:68)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at Request._execute (/project/node_modules/@hapi/hapi/lib/request.js:221:9)

Output of err variable:

Error [UnknownError]: An internal server error occurred
    at Object.extractError (/project/node_modules/aws-sdk/lib/protocol/json.js:51:27)
    at Request.extractError (/project/node_modules/aws-sdk/lib/protocol/rest_json.js:55:8)
    at Request.callListeners (/project/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/project/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/project/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/project/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/project/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /project/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/project/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/project/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners (/project/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
    at Request.emit (/project/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/project/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/project/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/project/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /project/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/project/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/project/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners (/project/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
    at callNextListener (/project/node_modules/aws-sdk/lib/sequential_executor.js:96:12)
    at IncomingMessage.onEnd (/project/node_modules/aws-sdk/lib/event_listeners.js:307:13)
    at IncomingMessage.emit (events.js:327:22)
    at IncomingMessage.EventEmitter.emit (domain.js:485:12)
    at endReadableNT (_stream_readable.js:1225:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) {
  code: 'UnknownError',
  time: 2020-05-27T16:55:25.862Z,
  requestId: undefined,
  statusCode: 500,
  retryable: true
}
shierro commented 4 years ago

I'm facing an issue somehow similar to this one.

When I access the app through the HTTP event(http://localhost:3000/staging/signupAttempt) I get the expected output.

But when I use the "HTTP Lambda" endpoint(POST | http://localhost:3000/2015-03-31/functions/signupAttempt/invocations) I get error

{
    "statusCode": 500,
    "error": "Internal Server Error",
    "message": "An internal server error occurred"
}

Mini-gist https://gist.github.com/shierro/e5136e34ae8ac12f7e3e94c7c6b7b555

"serverless-offline": "^6.4.0",
"serverless-plugin-typescript": "^1.1.9",
"serverless-webpack": "^5.3.2",
"typescript": "^3.9.5"

Serverless:
Framework Core: 1.73.1
Plugin: 3.6.13
SDK: 2.3.1
Components: 2.31.3

ScreenShot_20200625182721

shierro commented 4 years ago

pretty surprising, I also get the same error with a JS app using the "HTTP Lambda" endpoint

lyzs90 commented 4 years ago

i had to downgrade to serverless-offline 5.12.1, serverless 1.72.0

leengine90 commented 4 years ago

in my case, i added function name, and it worked well. so.. in serverless.yml

functions:
  foo: 
    handler: src/handler.index
    name: foo  ## <== add this 

I hope you guys go well

GonzaloSaad commented 4 years ago

In my case it was the order of the plugins.

I'm using serverless-offline-kinesis, and when I put the plugin before serverless-offline (as suggested here), I got the error. At that moment I had:

  - serverless-plugin-select
  - serverless-plugin-warmup
  - serverless-prune-plugin
  - serverless-python-requirements
  - serverless-dynamodb-local
  - serverless-offline-kinesis
  - serverless-offline

Then I changed it to:

  - serverless-plugin-select
  - serverless-plugin-warmup
  - serverless-prune-plugin
  - serverless-python-requirements
  - serverless-dynamodb-local
  - serverless-offline
  - serverless-offline-kinesis

And it worked. Why? I don't quite know. But I'll research in the other lib.

This is the package.json I have:

{
  "name": "my_api",
  "version": "a_cool_version",
  "private": true,
  "description": "",
  "author": "",
  "dependencies": {
    "serverless": "^1.71.3",
    "serverless-plugin-warmup": "^4.8.0",
    "serverless-python-requirements": "^5.1.0"
  },
  "devDependencies": {
    "serverless-offline": "^6.3.0",
    "serverless-offline-kinesis": "^4.0.1",
    "serverless-plugin-datadog": "^0.14.0",
    "serverless-dynamodb-local": "^0.2.39",
    "serverless-plugin-select": "^2.0.0-rc.1",
    "serverless-prune-plugin": "^1.4.2"
  }
}
mattia85 commented 4 years ago

In my case it was the wrong FunctionName passed to aws-sdk for lambda invocation.

wesklei commented 3 years ago

in my case, i added function name, and it worked well. so.. in serverless.yml

functions:
  foo: 
    handler: src/handler.index
    name: foo  ## <== add this 

I hope you guys go well

Thanks! This solved for me while using step functions local

josePPUP commented 11 months ago

in my case, i added function name, and it worked well. so.. in serverless.yml

functions:
  foo: 
    handler: src/handler.index
    name: foo  ## <== add this 

I hope you guys go well

Did not work for me 😢