actions-on-google-nodejs: AWS Lambda with API Gateway throwing response error

I’m experiencing the same issue outlined in this closed issue. I’m connecting to the lambda via API Gateway and it works fine if I do something like this:

exports.fulfillment = function (event: any, context: any, callback: any) {
    app.handler(event, {}).then((res) => {
        if (res.status !== 200) {
            callback(null, { fulfillmentText: `I got status code: ${res.status}` });
        } else {
            callback(null, res.body);
        }
    }).catch((e) => {
        callback(null, { fulfillmentText: `There was an error\n${e}` });
    });
};

I would love to be able to do it the way your documentation outlines, but if I do I get a TypeError:

{
    "errorMessage": "Cannot convert undefined or null to object",
    "errorType": "TypeError",
    "stackTrace": [
        "Function.keys (<anonymous>)",
        "Lambda.<anonymous> (/var/task/node_modules/actions-on-google/dist/framework/lambda.js:36:36)",
        "Generator.next (<anonymous>)",
        "/var/task/node_modules/actions-on-google/dist/framework/lambda.js:22:71",
        "new Promise (<anonymous>)",
        "__awaiter (/var/task/node_modules/actions-on-google/dist/framework/lambda.js:18:12)",
        "/var/task/node_modules/actions-on-google/dist/framework/lambda.js:30:46",
        "omni (/var/task/node_modules/actions-on-google/dist/assistant.js:44:53)"
    ]
}

I guess the ask in this issue is either:

  • get this working the way it is outlined in the docs exports.fulfillment = app;.
  • Update the docs to match the need for a lmbda wrapping function like I have above.

If I’m missing something in my Lambda or API Gateway config I’d be fine with changing/updating it. Just let me know!

Thanks, Tommy

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 7
  • Comments: 24 (11 by maintainers)

Most upvoted comments

I’m seeing the same issue but haven’t had time to look into a fix yet. I’ll have to check the proxy integration setting.

Ultimately, I think we just need better documentation for how to run Actions on Google projects on AWS Lambda correctly.

With the release of 2.6.0 through df48d7e1ac9a3172f2f7c3ec76c5767165c098a2, we added support to detect and parse different request formats from lambda.

Add support for other lambda formats

* Support for lambda entire body input format
* Support for lambda input body being an object

The response format is still the same as before. For now the way to perform custom response logic is still to manually call app.handler with your own code logic. But now the library will be able to handle most request formats on its own.

Let us know if there are any issues.

That would work, but it all depends on how API Gateway is configured. My team is currently using the below code to handle the eventuality of the event containing only the body, or containing the body and headers as you suggest.

On the response side, it would be nicer if the SDK could deal with the error handling and call the callback appropriately, but the format again depends on how API Gateway is configured. A fully documented example would be the most helpful thing for developers.

exports.handler = async (event, context, callback) => {
    const body = event.body || event
    const headers = event.headers || context.request.headers || []
    const result = await action.handler(body, headers);
    if (result.status >= 200 && result.status < 300) {
        callback(null, result.body);
    } else {
        callback(JSON.stringify(result));
    }
}

I’d like to be able to say exports.handler = app and for it to magically work whether the object passed in is a raw Lambda event (e.g. when running BST proxy) or an HTTP request event passed via API Gateway. That would be a good test of the value of the frameworks system in the V2 SDK.

I don’t personally mind losing the headers etc. that may be in the event object, as I would write my own wrapper function anyway if I wanted to handle those.