[SOLVED] ERR_MODULE_NOT_FOUND - Cannot find module.md
Guide to fix the pesky error of ERR_MODULE_NOT_FOUND with Javascript applications
Mar 23, 2023 | Read time 6 minutes🔔 Table of contents
Introduction
A common error that can come up when working with Node applications is the error of:
ERR_MODULE_NOT_FOUND]: Cannot find module
This generally means that whatever module you are trying to import is not being found.
A more descriptive error from the terminal looks like the below:
> node dist/app.js
node:internal/errors:465
ErrorCaptureStackTrace(err);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'redacted/dist/config/datadog' imported from /redacted/dist/app.js
at new NodeError (node:internal/errors:372:5)
at finalizeResolution (node:internal/modules/esm/resolve:405:11)
at moduleResolve (node:internal/modules/esm/resolve:966:10)
at defaultResolve (node:internal/modules/esm/resolve:1176:11)
at ESMLoader.resolve (node:internal/modules/esm/loader:605:30)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:318:18)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
at link (node:internal/modules/esm/module_job:78:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
Node.js v18.0.0
Process finished with exit code 1
So in the above error message, our app.js is importing the datadog
module. The erro comes up because the app.js code cannot find the datadog
module.
To fix this error, there are few things we can do:
- Check that you are using the
import
/export
syntax correctly - Make sure to have the file extension
.js
when you import - Make sure that the module exists and you have supplied the correct path.
- You are not mixing and matching with CommonJs - eg using the
require()
function
1. Check that you are using the import
/ export
syntax correctly
Firstly, if we want to make sure that we do not get this error, check that we are using the import and export syntax correctly.
As an example, lets say you have a file called helloModule.js which exports a function:
export function sayHello() {
console.log("Hello World!");
}
You can then import this function into another file - app.js using the import statement:
import { sayHello } from './helloModule.js';
sayHello(); // Output: Hello World!
In the above example, we are importing the helloModule.js to be used in our app.js file - the sayHello()
function.
Node will consider a file as ECMAScript modules when it satisfies the following:
- Files ending in .js if there is a top-level field “type” with a value of “module” in the nearest parent package.json file
- Files ending in .mjs
- Strings passed in as an argument to –eval or –print, or piped to node via STDIN, with the flag –input-type=module.
2. Make sure to have the file extension .js
when you import
One thing to keep in mind when doing import
is that the file MUST have an extension.
As specified in the Node docs - it is mandatory to have file extensions when working with import
keyword (https://nodejs.org/api/esm.html#mandatory-file-extensions)
Consider the following code:
import { sayHello } from './helloModule'; ❌ /* Will give you error - need .js extension */
import { sayHello } from './helloModule.js'; ✔️ /* This will work!*/
The first import will not work and will give you “ERR_MODULE_NOT_FOUND” since there is no extension (.js)
Note: The behavior tries to match how import behaves in browser environments
In the browser, imports still require file extensions (eg .js), but we can get around it using bundlers/ transpilers such as Webpack!
3. Make sure that the module exists and you have supplied the correct path.
One thing to keep in mind is that you are providing the correct path.
.
└── My project/
├── node_modules
├── common/
│ └── helloModule.js
├── app.js
├── db/
│ └── index.js
└── package.json
Now if we want to use helloModule.js in our app.js file, we have to make sure that the path is correct.
import { sayHello } from './helloModule.js'; ❌ /* Will give you error - wrong path */
import { sayHello } from './common/helloModule.js'; ✔️ /* This will work!*/
In the above, our helloModule.js is in the common
folder and we need to specify it relative to app.js
4. Check that not mixing and matching with CommonJs - eg using the require()
function
As specified in the Node docs (https://nodejs.org/api/esm.html) - Node comes with two module systems.
The old way to import javascript libraries or common code is to use CommonJS.
This uses the require()
function to load libraries that you want to use with your code.
Since Node version 14, ESM modules are introduced - which lets us use the import
/ export
keywords.
You should NOT mix and match ES6 modules and CommonJS syntax together!
You can only pick one module system - for example the below code will not work:
❌ /* will not work since mixing and matching require and import */
const { sayHello } = require('./helloModule.js');
import { sayHello } from './common/helloModule.js';
Convert to use ESM modules
If you already have require() methods to load your JS files and want to use the new ES6 module syntax with import
and export
, we can do the following:
- Replace
require()
, with theimport
keyword.
So instead of doing this:
const express = require('express');
We can convert to the new ES6 syntax with import/export. (Note: keep in mind that you still have the “type” value as “module”)
import express from 'express';
- In the package.json, make sure the “type” attribute is “module”.
For example:
{
"name": "TestApp",
"main": "server.js",
"type": "module", ✔️
...
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"chalk": "^4.0.0",
"dotenv": "^8.2.0",
"express": "^4.17.1"
},
"devDependencies": {
"sequelize-cli": "^5.5.1"
}
}
Convert to use CommonJS
The other option is to revert and keep using CommonJS.
To this this issue, we can do the following:
- Change the “type” value from “module” to “commonjs”
{
"type": "commonjs"
}
- Change all
import
torequire()
import express from 'express';
Becomes
const express = require('express');