aws / aws/aws-cdk

aws_lambda_nodejs: @smithy/service-error-classification Missing in Lambda 22_X Environment

Open
#33,099 5 comments 6 reactions 0 assignees View on GitHub
@aws-cdk/aws-lambda-nodejs bug effort/medium p3
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
1d 19h
Merged PRs (30d)
74

Description

### Describe the bug

When using the `aws-xray-sdk-core` package (possibly others as well) in a Lambda with the NodejsFunction using the now default `@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages` flag set to `true` it will fail to execute as the `@smithy/service-error-classification` will not be bundled and seems absent from the default packages installed in the runtime.

### Regression Issue

- [ ] Select this option if this issue appears to be a regression.

### Last Known Working CDK Version

The version before https://github.com/aws/aws-cdk/pull/31639 was merged and `"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true` was not the default.

### Expected Behavior

The bundled JS should work on the NodeJS 22 runtime.

Possible solutions:
- Use more granular `--external` options for the constructs bundling capabilities so the missing packages will get bundled instead of the complete exclusion of `@smithy/` at https://github.com/aws/aws-cdk/blob/ecbe1bf8e7e43d7423abfe93aa1c09189bf418c0/packages/aws-cdk-lib/aws-lambda-nodejs/lib/bundling.ts#L137
- Add the missing `@smithy/*` libraries like `@smithy/service-error-classification` (and possibly others) to the lambda environments bundled packages.

### Current Behavior

All `@smithy/*` packages are externalized by esbuild even though some might not be present in the lambda environment.

### Reproduction Steps

1. npx cdk init app --language typescript
2. Notice: `"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true` in the `cdk.json`
3. npm i esbuild @types/aws-lambda @smithy/service-error-classification

Stack:
```js
import * as cdk from 'aws-cdk-lib';
import { Duration } from 'aws-cdk-lib';
import { Architecture, Runtime } from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction, OutputFormat } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Construct } from 'constructs';

export class Stack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

const fn = new NodejsFunction(this, 'Lambda', {
entry: `${__dirname}/handler.ts`,
runtime: Runtime.NODEJS_22_X,
architecture: Architecture.X86_64,
timeout: Duration.seconds(30),

bundling: {
minify: false,
format: OutputFormat.ESM,
mainFields: ['module', 'main'],
//nodeModules: ['@smithy/service-error-classification'], // If not included, results in Runtime.ImportModuleError.
banner: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);", // https://github.com/evanw/esbuild/pull/2067
target: 'node22',
},
});
}
}
```

handler.ts
```
import { isClockSkewError } from '@smithy/service-error-classification';
import { Handler } from 'aws-lambda';

export const handler: Handler = async (event, context) => {
console.log('EVENT: \n' + JSON.stringify(event, null, 2));
return isClockSkewError(new Error(''));
};
```

This will result in the following asset bundle for the lambda code:
```js
import { createRequire } from 'module'; const require = createRequire(import.meta.url);

// lib/handler.ts
import { isClockSkewError } from "@smithy/service-error-classification";
var handler = async (event, context) => {
console.log("EVENT: \n" + JSON.stringify(event, null, 2));
return isClockSkewError(new Error(""));
};
export {
handler
};
```

And when executed will result in:
```
{
"errorType": "Error",
"errorMessage": "Cannot find package '@smithy/service-error-classification' imported from /var/task/index.mjs",
"trace": [
"Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@smithy/service-error-classification' imported from /var/task/index.mjs",
" at packageResolve (node:internal/modules/esm/resolve:844:9)",
" at moduleResolve (node:internal/modules/esm/resolve:913:18)",
" at moduleResolveWithNodePath (node:internal/modules/esm/resolve:1043:14)",
" at defaultResolve (node:internal/modules/esm/resolve:1086:79)",
" at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:650:12)",
" at #cachedDefaultResolve (node:internal/modules/esm/loader:599:25)",
" at ModuleLoader.resolve (node:internal/modules/esm/loader:582:38)",
" at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:241:38)",
" at ModuleJob._link (node:internal/modules/esm/module_job:132:49)"
]
}
```

### Possible Solution

As a workaround you can add the module problematic smithy modules to the `nodeModules` option of the `NodejsFunction` bundling options to ship them in the `node_modules` folder.

### Additional Information/Context

_No response_

### CDK CLI Version

2.176.0

### Framework Version

_No response_

### Node.js Version

22_X

### OS

macOS 15.2

### Language

TypeScript

### Language Version

_No response_

### Other information

See https://dev.classmethod.jp/articles/fix-cdk-nodejs-functions-bundle-error/ for more analysis

Contributor guide

Open the contributing guide

Research direction

Start with packages/aws-cdk-lib/aws-lambda-nodejs/lib/bundling.ts around line 137, then reproduce the Node.js 22 Lambda failure using the TypeScript handler and bundling settings shown in the issue. Compare the externalized @smithy packages with those available in the Lambda environment. Done means the reproduced bundled function executes successfully without requiring a manual nodeModules workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, node.js, typescript
Domain
build-system, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.