feat: Migrate aws-sdk v2 to @aws-sdk v3 for Node 20+ Lambda support#103
feat: Migrate aws-sdk v2 to @aws-sdk v3 for Node 20+ Lambda support#103mecham-lynn wants to merge 5 commits intomasterfrom
Conversation
…mbda support
AWS removed aws-sdk v2 from Lambda runtimes starting with Node 18,
causing all Lambdas to fail with "Cannot find module 'aws-sdk'" when
deployed via leo-cli to nodejs18.x or nodejs20.x runtimes.
Changes:
- Remove b.external("aws-sdk") from lib/build.js so AWS SDK is bundled in Lambda zips
- Replace all aws-sdk v2 imports with modular @aws-sdk v3 packages
- Migrate 6 files: lib/build.js, lib/leo-aws.js, lib/functionWrap.js,
lib/defaultCronRunner.js, docker-run.js, docker/run.js
- Services migrated: S3, Lambda, STS, DynamoDB, credential providers
- Remove aws-sdk v2 dependency, add @aws-sdk v3 modular packages
- Bump version to 4.0.0-awsv3
- Fix latent bug in docker-run.js error handler (callback was undefined)
Task: ES-2949
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
In v2, aws.config.credentials was a global singleton that all SDK clients automatically used. In v3 there is no global credential state, so the resolved temporary credentials must be explicitly exported as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN environment variables for the handler's SDK clients to pick up. Task: ES-2949 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…v3 correctness - S-2: Guard against corrupt/missing cached STS credentials in leo-aws.js - B-1: Use process.exit(1) on all error paths (docker-run.js, docker/run.js) - B-2: Add .catch() to top-level handler() calls for unhandled rejections - B-3: Guard against empty DynamoDB scan/get results in buildEvent() - B-4: Use NodeHttpHandler for DynamoDB client (correct v3 config shape) - B-5: Fix typo "Cannot fund function" → "Cannot find function" - C-1: Refactor docker-run.js and docker/run.js to consistent async/await - C-3: Remove dead role-assumption code block in functionWrap.js - C-5: Add explicit @aws-sdk/client-sts and @smithy/node-http-handler deps Task: ES-2949 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… zone `importModule` was declared with `let` after the `try/catch` block but called inside it, causing a ReferenceError at runtime. Converting to a `function` declaration leverages hoisting to fix this without moving code. Task: ES-2949 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| "aws-sdk": "^2.276.1" | ||
| "@aws-sdk/client-dynamodb": "^3.1010.0", | ||
| "@aws-sdk/client-lambda": "^3.1010.0", | ||
| "@aws-sdk/lib-dynamodb": "^3.1010.0" |
There was a problem hiding this comment.
Missing dependency in docker package.json breaks container
High Severity
docker/run.js requires @smithy/node-http-handler at line 26, but this package is not declared in docker/package.json. The Dockerfile runs npm install solely from docker/package.json, so the only reason this might resolve is if it happens to be hoisted as a transitive dependency of the listed @aws-sdk/* packages. Relying on undeclared transitive dependencies is fragile and can break across npm versions, lockfile changes, or alternative package managers.
Additional Locations (1)
If Lambda env vars set AWS_SESSION_TOKEN and the resolved credentials don't include a session token, the stale token would persist alongside new access key/secret, causing auth failures. Delete it in that case. Task: ES-2949 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>


Summary
aws-sdkv2 to modular@aws-sdkv3 packagesb.external("aws-sdk")fromlib/build.js— this was the root cause of Node 20 Lambda failures (Cannot find module 'aws-sdk')aws-sdkv2 dependency, add 6@aws-sdkv3 packages4.0.0-awsv3docker-run.jswhere error handler called undefinedcallback(now usesprocess.exit(1))Files Changed
lib/build.jsb.external("aws-sdk"), replaced credential handling with env vars +leo-awslib/leo-aws.jsaws.STS().credentialsFrom()andaws.SharedIniFileCredentialswith static creds andfromIni()lib/functionWrap.jsaws-sdkimport (only used in commented-out code)lib/defaultCronRunner.jsdocker-run.jsfromTemporaryCredentials), DynamoDB to v3docker/run.jspackage.jsondocker/package.jsonTest Plan
leo-cli@4.0.0-awsv3globallyleo-cli publisha Lambda project targetingnodejs20.xruntimeCannot find moduleerrors--profileflag)leo-cli test(local Lambda execution via functionWrap)Jira
Jira: https://chb.atlassian.net/browse/ES-2949
🤖 Generated with Claude Code
Note
Medium Risk
Broad migration of AWS service/credential codepaths (Lambda/S3/DynamoDB/STS) and packaging behavior; regressions could break local runners, profile-based auth, or deployed Lambda execution if v3 client semantics differ.
Overview
Migrates the CLI and docker lambda runners from
aws-sdkv2 to AWS SDK v3 (@aws-sdk/*+ Smithy handler), updating Lambda, S3, DynamoDB, and credential usage to the v3 client/command pattern.Fixes Node 20 runtime packaging issues by stopping
browserifyfrom externalizingaws-sdk(so the SDK is bundled when needed), and updates publishing/profile handling to resolve credentials vialeo-aws/AWS_PROFILEand pass explicit env creds to theaws s3CLI.Improves error handling in the docker runners (async
handler()with proper nonzero exits), adds explicit assumed-role env var precedence indocker-run.js, and bumps version to4.0.0-awsv3while updating dependencies/lockfile to removeaws-sdk.Written by Cursor Bugbot for commit 4b2ee27. This will update automatically on new commits. Configure here.