Serverless-offline: local invokes to 'http for lambda' throw an error (Python 3.8 runtime)

Created on 29 Apr 2020  ยท  9Comments  ยท  Source: dherault/serverless-offline

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

  • file: serverless.yml (reproduced with this minimal possible config)
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}
  • file: readOrg.handler (reproduced with this minimal possible code)
def handler(request, context):
    print("hello world")
  • source function code (not that it seems to matter as it can be reproduced via curl/postman)
data = {'test': 'test'}
lambda_client = boto3.client('lambda', endpoint_url='http://localhost:5005')
invoke_response = lambda_client.invoke(
    FunctionName='readOrg',InvocationType='RequestResponse',Payload=json.dumps(data))
logger.debug(f"invoke_response: {invoke_response}")

Expected behavior/code
Lambda handler is invoked with the requested payload.

Environment

  • serverless version: 1.6.8
  • serverless-offline version: 6.1.4
  • node version: v10.18.1
  • OS: macOS 10.15.4
  • python version: v3.8.2

Possible Solution
No known workarounds.

Most helpful comment

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

All 9 comments

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?

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
}

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

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

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

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

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"
  }
}

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

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ktwbc picture ktwbc  ยท  4Comments

Dong9769 picture Dong9769  ยท  4Comments

adambiggs picture adambiggs  ยท  4Comments

stunningpixels picture stunningpixels  ยท  3Comments

davidroman0O picture davidroman0O  ยท  4Comments