Skip to content

fix(instrumentation-aws-lambda): handle non-configurable exports from esbuild CJS bundles#3422

Open
RaphaelManke wants to merge 3 commits intoopen-telemetry:mainfrom
RaphaelManke:claude/inspiring-brahmagupta
Open

fix(instrumentation-aws-lambda): handle non-configurable exports from esbuild CJS bundles#3422
RaphaelManke wants to merge 3 commits intoopen-telemetry:mainfrom
RaphaelManke:claude/inspiring-brahmagupta

Conversation

@RaphaelManke
Copy link
Contributor

@RaphaelManke RaphaelManke commented Mar 9, 2026

Summary

  • When esbuild bundles ESM to CJS format, it defines exports using non-configurable accessor descriptors. OpenTelemetry's shimmer then fails with Cannot redefine property when trying to wrap the handler.
  • Adds a makeExportsConfigurable() helper in the Lambda instrumentation's patch callback that replaces such exports with a new object having configurable data descriptors before shimmer attempts patching.

Fixes: open-telemetry/opentelemetry-lambda#1781
See: evanw/esbuild#2199

Steps to reproduce

Create a handler that uses the same non-configurable export pattern that esbuild emits when bundling ESM to CJS:

// index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
Object.defineProperty(exports, "handler", {
  enumerable: true,
  get: function () { return handler; }
  // intentionally no configurable: true — this is what esbuild produces
});

async function handler(event) {
  return { statusCode: 200, body: JSON.stringify({ message: "OK" }) };
}

Deploy as a Lambda with the OTel layer and AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-handler:

zip handler.zip index.js

aws lambda create-function \
  --function-name otel-cjs-repro \
  --runtime nodejs20.x \
  --role <execution-role-arn> \
  --handler index.handler \
  --zip-file fileb://handler.zip \
  --layers arn:aws:lambda:<region>:184161586896:layer:opentelemetry-nodejs-0_20_0:1 \
  --environment "Variables={AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-handler}"

aws lambda invoke --function-name otel-cjs-repro \
  --cli-binary-format raw-in-base64-out \
  --payload '{}' response.json && cat response.json

Error (before fix):

{
  "errorType": "TypeError",
  "errorMessage": "Cannot redefine property: handler",
  "trace": [
    "TypeError: Cannot redefine property: handler",
    "    at Function.defineProperty (<anonymous>)",
    "    at T._wrap (...)",
    "    at Z.patch (...)",
    "    at T._onRequire (...)"
  ]
}

Root cause: esbuild emits exports as non-configurable accessor descriptors (see esbuild#2199), so Object.defineProperty in shimmer fails when trying to wrap the handler.

Test plan

  • Added test/lambda-test/esbuild-cjs.js simulating esbuild's non-configurable export pattern
  • Added integration tests verifying both success and error spans work with esbuild-style exports
  • Verified tests fail without the fix (TypeError: Cannot redefine property: handler)
  • Verified all 55 existing tests continue to pass
  • Normal CJS exports (already configurable) return the same object without creating a copy

… esbuild CJS bundles

When esbuild bundles ESM to CJS format, it defines exports using
non-configurable accessor descriptors. OpenTelemetry's shimmer then
fails with "Cannot redefine property" when trying to wrap the handler.

Add a makeExportsConfigurable() helper that replaces such exports with
a new object having configurable data descriptors before shimmer
attempts patching.

Fixes: open-telemetry/opentelemetry-lambda#1781
@github-actions github-actions bot requested a review from jj22ee March 9, 2026 10:26
@RaphaelManke RaphaelManke marked this pull request as ready for review March 9, 2026 10:27
@RaphaelManke RaphaelManke requested a review from a team as a code owner March 9, 2026 10:27
Copy link
Member

@raphael-theriault-swi raphael-theriault-swi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solution looks good, but I'm wondering whether we might want to tackle this from the instrumentation package given it's not technically unique to Lambda

@RaphaelManke
Copy link
Contributor Author

Can you point me in a direction? I am not sure which instrumentation you are referring to? Like in the core repo?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

3 participants