Skip to content

Node.js errorNode.js: “Error: Cannot find module”

A script, server or build stops with Error: Cannot find module, followed by a package name or a file path, and code MODULE_NOT_FOUND (with ES modules: ERR_MODULE_NOT_FOUND). Node.js looked everywhere it is allowed to look and found nothing. Either the package was never installed where the code runs, or the path in the require or import does not match a real file.

Short answer

Read the name in quotes. If it is a package name (like 'express'), run npm install in the folder that holds package.json, and check the package is under dependencies, not only devDependencies, if production installs skip dev packages. If it is a path ('./utils/db' or '/app/dist/index.js'), check the file exists at that path with that exact case, and that the build step that creates it ran. If it started after a Node.js upgrade, delete node_modules and run npm ci.

Why Node.js can’t find it, and the fix

  1. 01

    The package is not installed where the code runs

    “If it is not found there, then it moves to the parent directory, and so on, until the root of the file system is reached.” Node.js, Modules: CommonJS modules

    For a bare name like 'express', Node.js walks up from the current file through every node_modules folder to the root of the disk. If the package is not in any of them, the error appears. This is common after cloning a repo, after switching branches that changed package.json, or on a server where the install ran in a different folder.

    # in the folder that holds package.json
    npm install
    
    # a single missing package
    npm install express
  2. 02

    Production skipped devDependencies

    Hosts and Docker images often install with npm ci --omit=dev or NODE_ENV=production. Anything the running app needs at runtime must be in dependencies. A package used only by the build (TypeScript, a bundler) can stay in devDependencies if the build runs before the dev packages are dropped.

    # move a runtime package to dependencies
    npm install --save-prod dotenv
  3. 03

    The relative path is wrong

    A name starting with ./ or ../ is resolved from the folder of the file that contains the require, not from where you started node. Check the spelling and the case: macOS ignores case by default, but Linux servers and most CI do not, so ./Utils/db works on a Mac and fails on deploy. With ES modules (import), include the file extension, such as ./db.js.

  4. 04

    The entry file is not built yet

    Errors like Cannot find module '/app/dist/index.js' mean the start command points at build output that does not exist. Run the build before start (npm run build, then npm start), check the outDir in tsconfig.json matches the path in package.json, and make sure the build output is not excluded from the deploy.

    // package.json
    "scripts": {
      "build": "tsc",
      "start": "node dist/index.js"
    }

Checked against the vendor’s docs on : Node.js: Modules: CommonJS modules (loading from node_modules folders); Node.js: Errors (MODULE_NOT_FOUND).

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: “Cannot use import statement outside a module” · Vercel “Module not found: Can’t resolve” · Node.js ENOENT: no such file or directory · Node.js ERR_MODULE_NOT_FOUND

Questions

More on this error

It works on my machine but fails on the server. Why?

Usually one of three things: the server installs without devDependencies, the server’s file system is case sensitive and an import has the wrong case, or the build output the start command needs was never created there. Compare the install command and the start command on both.

Should I delete node_modules?

It helps when the error started after a Node.js upgrade or a half-finished install. Delete node_modules and run npm ci, which installs exactly what the lockfile lists. Do not delete the lockfile unless you mean to update every package.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.