Using ES Modules breaks when a directory with the same name as the module exists

Open
#93 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
35/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
node.js, typescript
Domain
backend

Research direction

Read src/UserFunction.js around lines 73 and 133-174, then reproduce the issue with the described package.json, hello-world.js, and hello-world/ setup using the Node.js 20 runtime in verbose mode. Done means the handler loads successfully when a directory shares the module name, without the reported ImportModuleError.

Written by the indexing model from the issue text.

Description

If you setup a project with the following structure:

  1. "type": "module" in package.json
  2. A hello-world.js file
  3. A hello-world/ folder
  4. Use hello-world.lambdaHandler as your module/handler
  5. Enable verbose mode, e.g. with ENV AWS_LAMBDA_RUNTIME_VERBOSE 1 in a Docker container using public.ecr.aws/lambda/nodejs:20, so you can see the verbose messages

This is the resulting log.

START RequestId: 99e7b316-ab71-4bd2-8aed-85df8b0aeaaf Version: $LATEST
2023-12-13T01:13:42.274Z        undefined       INFO    RUNTIME LOADER Try loading as commonjs:  hello-world  with paths: , /var/task 
2023-12-13T01:13:42.275Z        undefined       INFO    RUNTIME LOADER Try loading as commonjs: /var/task/hello-world
2023-12-13T01:13:42.276Z        undefined       INFO    RUNTIME LOADER globalPaths ["/opt/nodejs/node20/node_modules","/opt/nodejs/node_modules","/var/runtime/node_modules","/var/runtime","/var/task","/root/.node_modules","/root/.node_libraries","/var/lang/lib/node"]
2023-12-13T01:13:42.276Z        undefined       ERROR   Uncaught Exception      {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module '/var/task/hello-world'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module '/var/task/hello-world'","Require stack:","- /var/runtime/index.mjs","    at _loadUserApp (file:///var/runtime/index.mjs:1087:17)","    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1119:21)","    at async start (file:///var/runtime/index.mjs:1282:23)","    at async file:///var/runtime/index.mjs:1288:1"]}
13 Dec 2023 01:13:42,288 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 129 InvokeID=
2023-12-13T01:13:42.351Z        undefined       INFO    RUNTIME LOADER Try loading as commonjs:  hello-world  with paths: , /var/task 
2023-12-13T01:13:42.352Z        undefined       INFO    RUNTIME LOADER Try loading as commonjs: /var/task/hello-world
2023-12-13T01:13:42.353Z        undefined       INFO    RUNTIME LOADER globalPaths ["/opt/nodejs/node20/node_modules","/opt/nodejs/node_modules","/var/runtime/node_modules","/var/runtime","/var/task","/root/.node_modules","/root/.node_libraries","/var/lang/lib/node"]
2023-12-13T01:13:42.353Z        undefined       ERROR   Uncaught Exception      {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module '/var/task/hello-world'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module '/var/task/hello-world'","Require stack:","- /var/runtime/index.mjs","    at _loadUserApp (file:///var/runtime/index.mjs:1087:17)","    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1119:21)","    at async start (file:///var/runtime/index.mjs:1282:23)","    at async file:///var/runtime/index.mjs:1288:1"]}
END RequestId: a879dd58-2f3f-458a-9911-dbb92b552019
REPORT RequestId: a879dd58-2f3f-458a-9911-dbb92b552019  Init Duration: 0.29 ms  Duration: 156.42 ms       Billed Duration: 157 ms Memory Size: 128 MB     Max Memory Used: 128 MB
{"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module '/var/task/hello-world'\nRequire stack:\n- /var/runtime/index.mjs","trace":["Runtime.ImportModuleError: Error: Cannot find module '/var/task/hello-world'","Require stack:","- /var/runtime/index.mjs","    at _loadUserApp (file:///var/runtime/index.mjs:1087:17)","    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1119:21)","    at async start (file:///var/runtime/index.mjs:1282:23)","    at async file:///var/runtime/index.mjs:1288:1"]}

Cause

Before trying to load a module an extensionless import is attempted. Because fs.existsSync does not differentiate between a directory and a file it returns true and a require on the directory is attempted without any try catch.

https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/blob/7374a4e338fc3b070811d55ee337740f3f6cb382/src/UserFunction.js#L133-L174

https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/blob/7374a4e338fc3b070811d55ee337740f3f6cb382/src/UserFunction.js#L73

Background

I was working on a project using multiple ESModules based lambda functions. The code was transpiled from TypeScript and because some code needed to be shared between functions I had a hello-world.js in the root that was export * from './dist/hello-world/src/app.js'; to so the lambda function ran off the transpiled code.

Dominant language
TypeScript
Stars
224
Forks
60
Avg merge
26m
Merged PRs (30d)
2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from aws/aws-lambda-nodejs-runtime-interface-client

All issues in aws/aws-lambda-nodejs-runtime-interface-client

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.