I'm trying to get a start with AWS by starting at the beginning, running the Build a Basic Web Application tutorial. I figured I'd be able to just follow it step by step and have a simple Hello World web page front end to a little database. But I'm running into a strange error: including the bare-bones, default aws-sdk
module is failing!
Short version:
This code:
// Include the AWS SDK module
const AWS = require('aws-sdk');
generates this error: Error: Cannot find module 'aws-sdk'
Long Story:
I'm following the process step by step, creating all the pieces using the AWS online tools. The first hint of trouble happened when I created my Lambda function. I wasn't too worried that the Create Function tool shows a Node.js version of 18.x instead of the tutorial's Node.js 16.x, but I definitely noticed that the Lambda shell it generated was named index.mjs
instead of index.js
. No problem, I'll just use that file. I replaced the contents with Amazon's HelloWorld code.
// Define handler function, the entry point to our code for the Lambda service
// We receive the object that triggers the function as a parameter
exports.handler = async (event) => {
// Extract values from event and format as strings
let name = JSON.stringify(`Hello from Lambda, ${event.firstName} ${event.lastName}`);
// Create a JSON object with our response and store it in a constant
const response = {
statusCode: 200,
body: name
};
// Return the response constant
return response;
};
I set up the Test Event functionality using their data:
{
"firstName": "Ada",
"lastName": "Lovelace"
}
But running the code generated my first error: exports is not defined in ES module scope
Doing some searching on that error sent me down a rabbit hole far outside the scope of a basic tutorial, so I renamed the file from index.mjs to index.js. Rebuilt and poof, it worked just fine:
{
"statusCode": 200,
"body": "\"Hello from Lambda, Ada Lovelace\""
}
I won't go through the steps of creating the database, because that's not relevant. Everything was fine until I replaced the code with the code that would access the database - it errored with the message above. To simplify the issue, I deleted the Lambda and rebuilt it with the working code above, and the require
statement:
// Include the AWS SDK module
const AWS = require('aws-sdk');
// Define handler function, the entry point to our code for the Lambda service
// We receive the object that triggers the function as a parameter
exports.handler = async (event) => {
// Extract values from event and format as strings
let name = JSON.stringify(`Hello from Lambda, ${event.firstName} ${event.lastName}`);
// Create a JSON object with our response and store it in a constant
const response = {
statusCode: 200,
body: name
};
// Return the response constant
return response;
};
Running that generates this output:
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'aws-sdk'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/index.mjs",
"trace": [
"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"
]
}
The strangest thing I see in the dump: it still references index.mjs
even though I deleted the file (or renamed it - I tried both ways). In the online IDE, I only have access to the file tree that shows only index.js. I assume that's /var/task
so I don't know where /var/runtime
is that still contains a reference to index.mjs
.
I'm looking forward to the solution to this head-scratcher. It feels like it's simple enough that it should Just Work!
The code provided by the that tutorial will not work with Lambda Runtime using NodeJS 18. There are a few reasons for this:
Node.js 18.x is using AWS SDK v3. In your code, you are trying to import AWS SDK v2. The problem is that, NodeJS 18.x runtime does not come with version 2 of the AWS SDK automatically packaged and ready to use. This is the reason why you got the error for not being able to find aws-sdk
. The newer v3 SDK is significantly different from the older v2 version.
exports is not defined in ES module scope
- the reason for this error is that Node.js 18.x runtime is using ECMAScript modules instead of CommonJS modules. This is why you are seeing a JavaScript file with an .mjs
extension. Suffice to say, ECMAScript modules export dependencies differently (using export
keyword), likewise they use import
instead of require
for importing dependencies.
Update and warning for newer readers:
Support for NodeJS 16.x was dropped by AWS, so you may not be able to proceed with the steps bellow!
Since you are doing a tutorial, I suggest sticking with NodeJS 16 (or lower available version) for now. Migrating to NodeJS 18.x is not as a trivial task as you might expect, but is not the end of the world as long as you have the necessary experience. Hopefully, this tutorial will be updated in the future for the latest available runtimes.
To create a function using NodeJS 16.x you can select the runtime from the list: