Hey, there!
Today I spent a good few hours trying to solve a problem on AWS Lambda and given how deep the problem was, I thought it would be a good idea to share the solution.
โ๏ธ The Context
I am using Jovo Framework to develop a voice app for both Alexa and Google Assistant and one of their guides teach how to deploy the code to an AWS Lambda function using serverless CLI.
๐ The Problem
After setting everything up and having the code deployed successfully, when trying to run the lambda function the following error was popping up in the cloud logs
{
"errorType": "TypeError",
"errorMessage": "Cannot redefine property: handler",
"trace": [
"TypeError: Cannot redefine property: handler",
" at Function.defineProperty (<anonymous>)",
" at defineProperty (/opt/otel-extension/node_modules/shimmer/index.js:14:10)",
" at AwsLambdaInstrumentation.wrap [as _wrap] (/opt/otel-extension/node_modules/shimmer/index.js:56:3)",
" at InstrumentationNodeModuleFile.patch (/opt/otel-extension/node_modules/@opentelemetry/instrumentation-aws-lambda/src/instrumentation.ts:124:20)",
" at AwsLambdaInstrumentation._onRequire (/opt/otel-extension/node_modules/@opentelemetry/instrumentation/src/platform/node/instrumentation.ts:109:23)",
" at /opt/otel-extension/node_modules/@opentelemetry/instrumentation/src/platform/node/instrumentation.ts:143:25",
" at Module.Hook._require.Module.require (/opt/otel-extension/node_modules/require-in-the-middle/index.js:154:32)",
" at Module.Hook._require.Module.require (/opt/otel-extension/node_modules/require-in-the-middle/index.js:80:39)",
" at Module.Hook._require.Module.require (/opt/otel-extension/node_modules/require-in-the-middle/index.js:80:39)",
" at Module.Hook._require.Module.require (/opt/otel-extension/node_modules/require-in-the-middle/index.js:80:39)"
]
}
Note: in the image above the error shows as "Cannot redefine property: myHandler" because I've changed the function name for debugging purposes.
The easiest way to reproduce the error was using the Test feature from AWS Lambda with an Alexa Start Session template.
๐ค The culprit
It took me a while to notice that, according to the stack trace, the error was happening in a dependency of otel-extension
: shimmer
at defineProperty (/opt/otel-extension/node_modules/shimmer/index.js:14:10)
Shimmer is a monkeypatching library that a telemetry extension for AWS Lambda was using.
According to this issue, the problem is using esbuild bundle generator - that Jovo uses - with this telemetry extension.
The responsible for actually adding this telemetry extensions as an AWS Lambda layer was serverless cli.
๐ง The solution
As suggested in both opentelemetry-js-contrib and aws-otel-lambda issues, the solution is changing ES6 export
to CommonJS module.exports
.
Instead of
export const handler = () => {
// removed for brevity
};
Do this
const handler = () => {
// removed for brevity
};
module.exports = { handler }
But, since I'm using Jovo with AWS Lambda, I actually had to change the app.prod.ts
file (where prod
can be other stage name you defined while running jovo new:stage <stage>
).
// app.prod.ts
import { app } from './app'
import { handler } from './server.lambda'
app.configure({
//...
})
module.exports = { handler }
๐ The Conclusion
I was sure that I was doing something wrong in some configuration step, since this setup involves several services: Jovo, Serveless, AWS Lambda and AWS API Gateway.
It was kinda relieving to know that the problem was actually a compatibility issue between esbuild and open-telemetry.
Nonetheless, I was able to learn a lot about these services as usual with any deep debugging problem we have to deal as developers.
Top comments (0)