Skip to content

Node.js layer: "Cannot redefine property: handler" when using esbuild #1781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
smagura-jm opened this issue Apr 17, 2025 · 4 comments
Closed
Labels
bug Something isn't working

Comments

@smagura-jm
Copy link

Describe the bug
The Node.js layer is working correctly when using a handwritten CommonJS handler like this:

module.exports = {
  handler: () => 200
}

My real code is written in ES Modules and is bundled via esbuild. Compile the following code with esbuild and then deploy it to Lambda.

export const handler = () => 200;

Now, the Lambda fails with the error

{
  "errorType": "TypeError",
  "errorMessage": "Cannot redefine property: handler",
  "stack": [
    "TypeError: Cannot redefine property: handler",
    "    at Function.defineProperty (<anonymous>)",
    "    at n (/opt/wrapper.js:1:242970)",
    "    at i (/opt/wrapper.js:1:243369)",
    "    at o._wrap (/opt/wrapper.js:1:252372)",
    "    at x.patch (/opt/wrapper.js:1:204436)",
    "    at /opt/wrapper.js:1:254659",
    "    at Array.reduce (<anonymous>)",
    "    at t._onRequire (/opt/wrapper.js:1:254445)",
    "    at t (/opt/wrapper.js:1:255685)",
    "    at Module.T (/opt/wrapper.js:1:92076)"
  ]
}

Steps to reproduce

  1. Clone the opentelemetry-lambda repo and execute npm run build in the nodejs directory. This produces a layer.zip file.
  2. Upload layer.zip as a layer via the AWS Console.
  3. Create a new Lambda function (Node.js 22.x) and add the layer to it.
  4. In the environment variables for the Lambda, set AWS_LAMBDA_EXEC_WRAPPER to /opt/otel-handler.
  5. Locally, create index.js as
    export const handler = () => 200;
  6. Bundle the code using esbuild by running npx esbuild index.js --platform=node --bundle --outfile=compiled.js. View the compiled bundle here
  7. Paste the compiled code into the code editor for the Lambda function in the AWS Console. Click "Deploy".
  8. In the AWS Console, test the Lambda function with an arbitrary payload.

What did you expect to see?
The Lambda succeeds.

What did you see instead?
The Lambda fails with the error

{
  "errorType": "TypeError",
  "errorMessage": "Cannot redefine property: handler",
  "stack": [
    "TypeError: Cannot redefine property: handler",
    "    at Function.defineProperty (<anonymous>)",
    "    at n (/opt/wrapper.js:1:242970)",
    "    at i (/opt/wrapper.js:1:243369)",
    "    at o._wrap (/opt/wrapper.js:1:252372)",
    "    at x.patch (/opt/wrapper.js:1:204436)",
    "    at /opt/wrapper.js:1:254659",
    "    at Array.reduce (<anonymous>)",
    "    at t._onRequire (/opt/wrapper.js:1:254445)",
    "    at t (/opt/wrapper.js:1:255685)",
    "    at Module.T (/opt/wrapper.js:1:92076)"
  ]
}

What version of collector/language SDK version did you use?
I cloned the opentelemetry-lambda repo, and the latest commit on main was 939cecd.

What language layer did you use?
Node.js

@smagura-jm smagura-jm added the bug Something isn't working label Apr 17, 2025
@serkan-ozal
Copy link
Contributor

Hi @smagura-jm,

Unfortunately, this is the limitation of the shimmer which is the library OTEL JS SDK uses for monkey patching to instrument user handler. esbuild generate immutable objects which are not writeable and this is the point where shimmer fails.

Here are related issues and their discussions:

So, the only solution (workaround) I see is converting your handler

from

export const handler = () => 200;

to

const handler = () => 200;

module.exports = { handler }

@smagura-jm
Copy link
Author

Thanks for your answer! It's unfortunate that it doesn't work without the workaround. Closing the issue.

@serkan-ozal
Copy link
Contributor

Thanks @smagura-jm.

Did it work?

const handler = () => 200;

module.exports = { handler }

@smagura-jm
Copy link
Author

Yes, that worked.

I was actually able to get this to work in my real codebase by converting my handler files to CommonJS modules. My code is still able to use the import syntax, even though it is CommonJS (I did not realize that was possible). All of my non-handler files are still in ES Modules.

Thanks!

@smagura-jm smagura-jm closed this as not planned Won't fix, can't repro, duplicate, stale Apr 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants