43

I am trying to access S3 via aws-sdk in my lambda function.

import S3 from 'aws-sdk/clients/s3';

const s3 = new S3();
const { Contents: results } = await s3.listObjects({ Bucket: process.env.DOCUMENTS_BUCKET_NAME! }).promise()

I have also deployed it successfully using cdk deploy command. But when I test, I get the following error

2022-11-23T15:53:40.891Z    undefined   ERROR   Uncaught Exception  
{
    "errorType": "Runtime.ImportModuleError",
    "errorMessage": "Error: Cannot find module 'aws-sdk'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/index.mjs",
    "stack": [
        "Runtime.ImportModuleError: Error: Cannot find module 'aws-sdk'",
        "Require stack:",
        "- /var/task/index.js",
        "- /var/runtime/index.mjs",
        "    at _loadUserApp (file:///var/runtime/index.mjs:1000:17)",
        "    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1035:21)",
        "    at async start (file:///var/runtime/index.mjs:1200:23)",
        "    at async file:///var/runtime/index.mjs:1206:1"
    ]
}

As per the documentation, aws-sdk is always available in the runtime.

Does anyone know what am I doing wrong?

Thank you very much

2
  • Based on the fact that your code is calling the legacy listObjects method rather than listObjectsV2 and is using the .promise() feature, you appear to be trying to use JavaScript SDK v2, so const AWS = require('aws-sdk'); const s3 = new AWS.S3(); Commented Nov 23, 2022 at 16:27
  • Or use SDK v3 as documented here. Commented Nov 23, 2022 at 16:28

7 Answers 7

47

If your lambda runtime is nodejs18.x or above my understanding is that AWS SDK v2 is not included in the runtime. (It was for nodejs16.x and below)

So, the best solution would be to switch to v3 SDK https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/

Or, as a workaround in the short term if you use webpack and usually exclude bundling aws-sdk with the following:

externals: {
    'aws-sdk': 'aws-sdk'
},

Then simply leave externals out of your webpack.config.js and it will be bundled, but will of course make your lambda larger so not ideal

Or use nodejs16.x or below in the short term

Sign up to request clarification or add additional context in comments.

2 Comments

using nodejs16.x fix my problem. But I don't know why. Obviously, the same code worked at nodejs18.x before. do runtime nodejs18.x remove SDK v2 now?
Link to AWS Blog about this change regarding Node 16 vs Node 18 and its supported AWS SDK version: aws.amazon.com/blogs/compute/…
15

UPDATED LINK

Thank you @jarmod, I needed the following dependency

@aws-sdk/client-s3

My commit with the fix is available here

2 Comments

The link for the commit is broken
yes, please provide the correct link.
6

For those using serverless framework with esbuild, the plugin excludes 'aws-sdk' by default. In my case, I didn't downgrade to v16, I kept v18 and put an empty array in my serverless.yml

custom:
  esbuild:
    exclude: []

2 Comments

Thank you! I missed that esbuild excluded aws-sdk by defualt.
It should be noted that doing this will inflate your bundle and (depending on your usage plan) could be more costly.
5

In my case I had to switch to v3 sdk using this guide --> https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-dynamodb-utilities.html#dynamodb-example-document-client-query

My code changed from

const AWS = require("aws-sdk");

export const handler = async (event) => {
  var data = await DynamoDBClient.scan({ TableName: "dcn" }).promise();
  const response = {
    statusCode: 200,
    body: JSON.stringify(data),
  };
  return response;
};

to something like:

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { QueryCommand, DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);

export const handler = async (event) => {
  //var data = await DynamoDBClient.scan({ TableName: "dcn" }).promise();
  const command = new QueryCommand({
    TableName: "dcn",
    KeyConditionExpression:"id = :id",
    ExpressionAttributeValues: {":id":"xyz"},
    ConsistentRead: true,
  });
  const dbResp = await docClient.send(command);
  const response = {
    statusCode: 200,
    body: JSON.stringify(dbResp),
  };
  return response;
};

However it is not achiving the same effect as the older code, which was retrieving all the data from teh table while the new code just retrieves a particular key.

Comments

2

I also encountered this problem. I picked Node.js v18 when creating Lambda. It was giving me the same error. But changing the package to "@aws-sdk/*" new versions solved the problem.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
1

What I did to fix this issue was to just downgrade my runtime settings from Node.js 18 to Node.js 16.x or below. After that, the test went successful.

1 Comment

Node.js 18 has numerous security enhancements, downgrading should be a last resort.
-1

For those struggling with the Lambda upgrade from Node 16 to 18+, I kept getting this error until I did the following:

  1. Update Runtime from Node 16 to Node 20
  2. Update the code to import instead of require targeting the module that I needed import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses"; in my case (and other code changes as needed based on updated import)
  3. Rename the index.js file to index.mjs
  4. The tests kept failing, but after publishing the function they succeeded.

Obviously, this is pretty risky, publishing prior to successful test, so you should try this in a qa environment or with an unused function first.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.