'Cannot find module' and 'ModuleNotFoundError' on deploy

The runtime tried to import a module and could not find it, either because the package is not installed or because the path is wrong. Read the module name in the message, then check dependencies, file path, letter case and file extension.

Updated 7 min read

Learning objectives

After reading this article you will be able to:

  • Tell a missing package apart from a wrong file path
  • Fix the Node.js and Python versions of the error step by step
  • Prevent the error from coming back on the next deploy
On this page

Your app started fine on your computer, you deployed it, and the log ends with one of these:

text
Error: Cannot find module 'express'
Require stack:
- /app/index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1517:15)
    ...
    at Module._compile (node:internal/modules/cjs/loader:1871:14) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/app/index.js' ]
}
text
ModuleNotFoundError: No module named 'discord'

Both messages say the same thing: an import or require named something the runtime could not locate. The fix is almost never mysterious, but you have to read the message before guessing. The name inside the quotes tells you which of two families of problem you have.

Cannot findmodule 'x'read the name'express'bare namein package.json?only devDependencies?did the install run?'./utils'pathwas the file shipped?same letter case?extension .js (ESM)?build output?
The quoted name picks the branch: a bare package points to dependencies, a path points to the file.

What do these errors actually mean?#

In Node.js, require() throws MODULE_NOT_FOUND when the path or package does not exist. The ES module version, import, throws ERR_MODULE_NOT_FOUND. In Python, ModuleNotFoundError is a subclass of ImportError, raised when a module could not be located (Python docs).

Here is the ES module form, for a missing package and for a relative file:

text
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'express' imported from /app/index.js

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/utils' imported from /app/index.js
Did you mean to import "./utils.js"?

Look at what the name looks like:

  • A bare name (express, discord): a package that is not installed where the app runs.
  • A path (./utils, /app/utils): a file the runtime could not find at that exact location.

Everything below follows that split.

Is the package missing from dependencies?#

This is the most common cause. For a bare package name, Node.js starts in the folder of the current file, looks in node_modules, then walks up through the parent folders until the root of the file system (Node.js docs). If no node_modules on that path contains the package, you get the error.

Check these in order:

  1. Is it in package.json? If you installed it with npm install express it is listed. If you copied code from a tutorial and never installed it, it is not.
  2. Is it in devDependencies only? npm says dependencies is for runtime packages and devDependencies is for tools that users of your module do not need, such as test harnesses and transpilers (npm docs). A production install can skip dev packages, and npm ci omits them by default when NODE_ENV is production (npm docs). If your app imports it at runtime, move it:
bash
npm install --save-prod express
  1. Did the install actually run on the server? Uploading the node_modules folder from your PC is not reliable. Ship package.json plus the lockfile and install from them.

npm ci is the right command for a clean install. It requires an existing package-lock.json, deletes any existing node_modules, and exits with an error instead of updating the lockfile when package.json and the lockfile disagree. That last behavior is useful: it turns a silent mismatch into a loud failure.

bash
npm ci
node index.js

If npm ci fails because the lockfile is out of sync, run npm install locally, commit the updated lockfile, and deploy again.

Is the file path, case or extension wrong?#

When the name is a path, the cause is a file that is not where the import says it is.

Letter case. On Linux, ./Utils.js and ./utils.js are two different files. Windows and macOS file systems usually ignore case, so an import with the wrong case works on your machine and fails on the server. Rename the file or fix the import so they match exactly. If you rename only the case of a file, make sure your Git client records the change, because some setups ignore it.

Missing extension in ES modules. With import, relative specifiers need the extension, and directory indexes must be fully specified (Node.js ESM docs). This works with require in CommonJS but not with import:

js
// Fails in an ES module: ERR_MODULE_NOT_FOUND
import { helper } from "./utils";

// Works
import { helper } from "./utils.js";
import { setup } from "./startup/index.js";

Your app is an ES module when package.json has "type": "module" or the file ends in .mjs. If you are using TypeScript with a bundler locally, imports without extensions may work there and break when you run the output directly.

A file that was never uploaded. Check that the file is in your ZIP or commit. Common culprits are a .gitignore line or an upload that skipped a folder. In a monorepo, a shared package that sits outside the folder you deployed will be missing too.

Is the main file or build output wrong?#

Some projects compile to a dist or build folder. If your start command points at dist/index.js and the build step never ran, or dist is ignored by version control, the entry point itself is missing:

text
Error: Cannot find module '/app/dist/index.js'

Confirm three things: the build command runs before start, the output folder is part of what you deploy (or is produced on the server), and the main file in your configuration matches the real path. Also check "main" in package.json if you import the package by name, since a missing or unresolvable main with no index.js reports the whole module as missing (Node.js docs).

Why does Python say "No module named"?#

The Python version has its own set of causes.

The package is not installed. Install it, and record it so the next environment gets it too:

bash
python -m pip install discord.py
python -m pip freeze > requirements.txt

Then on the target, python -m pip install -r requirements.txt. The pip docs describe this freeze-then-install flow, and also note that pip freeze does not compute a lockfile or a solver result (pip docs). For a fully pinned setup, use a lockfile tool.

The import name differs from the install name. This trips up many people:

You write You install
import yaml PyYAML
import PIL Pillow
import cv2 opencv-python
import dotenv python-dotenv
import discord discord.py

Wrong interpreter. pip and python can belong to different installs. Use python -m pip install ... so the package goes to the interpreter that will run your code. Inside a virtual environment, activate it first.

A local file shadows or misses the module. A file named discord.py or random.py in your project can hide the real package. For your own modules, check that the folder layout matches the import and that you run the app from the expected working directory.

How do you diagnose it quickly?#

Start from the message:

  1. Copy the exact module name from the log.
  2. Bare name? Run npm ls express (Node.js) or python -m pip show discord.py (Python) in the same environment that runs the app.
  3. Path? List the folder and compare the name character by character, including case and extension.
  4. Still stuck? Run the failing import in isolation:
bash
node -e "require.resolve('express')"
node --input-type=module -e "await import('express')"
python -c "import discord; print(discord.__file__)"

require.resolve throws MODULE_NOT_FOUND when it cannot find the module, so it shows what the runtime sees without starting your whole app.

One more Node.js case: require() can load an ES module only if it has no top-level await, otherwise it throws ERR_REQUIRE_ASYNC_MODULE (Node.js docs). That is a different error, but it shows up in the same place. Switch to import() in that situation.

How do you stop it from coming back?#

  • Treat the lockfile as part of the code: commit package-lock.json, and use npm ci for installs.
  • Keep runtime packages in dependencies.
  • Name files in lowercase and import them with the exact same spelling.
  • In ES modules, always write the extension.
  • Pin Python packages in requirements.txt and install with the same interpreter that runs the app.
  • Test the deployed shape locally: delete node_modules, run npm ci, then start the app. If it fails there, it will fail on the server.

For related deploy failures, see how to read build errors, how to read app logs and how to host a Node.js app.

How to do this on Square Cloud#

On Square Cloud you deploy by uploading a ZIP, using the CLI, pushing to GitHub or using the VS Code extension. Whichever you pick, the first check is the same: open the real-time logs, copy the module name from the error, and compare it with the files you actually uploaded. On start, the platform runs npm install when there is no node_modules, with NODE_ENV=production: a package that is only in devDependencies is not installed and causes this error.

The in-browser file manager shows the files in your application, so you can confirm that the path in the error exists and that its letter case matches. The editor saves straight to the application without a redeploy.

If the error names your entry file, check that the main file setting points to a file that exists. That setting lives in squarecloud.app, which is optional: the dashboard can generate it on deploy (runtime, memory, main file), or you can write it at the project root. There is no build step, so an entry point in dist means uploading the compiled folder or putting the build in your start command.

Once you have the fix locally, send it with the CLI commit command or by pushing to GitHub through the official GitHub Action, which can run commit --restart on every push. The CLI page walks through the commit workflow.

Deploy

Push from GitHub, the CLI or a ZIP and go live in seconds

Learn more

FAQs

What is the difference between MODULE_NOT_FOUND and ERR_MODULE_NOT_FOUND?

MODULE_NOT_FOUND is the code Node.js sets when require() (CommonJS) cannot resolve a path. ERR_MODULE_NOT_FOUND is the code for the same failure with import (ES modules). The causes overlap, but ES modules also require a full file extension on relative imports.

Why does my app work on my PC but fail with 'Cannot find module' after deploy?

Your machine has files and packages the deployed copy does not: a globally installed package, a node_modules folder you never upload, a package that is only in devDependencies, or a file whose name differs in letter case. Linux treats Utils.js and utils.js as different files, Windows and macOS usually do not.

Does ModuleNotFoundError mean I should run pip install?

Usually, but check the package name first. The import name and the install name often differ: import yaml comes from PyYAML, import PIL from Pillow, import cv2 from opencv-python. Also confirm pip installs into the same Python interpreter that runs your app.

Should I upload my node_modules folder?

No. Ship package.json and the lockfile, and install on the target with npm ci or your package manager's equivalent. A node_modules folder built on another operating system can contain binaries that do not run elsewhere.

Next articleServerless vs containers for bots and APIsServerless runs functions per request and scales to zero; a container keeps a process running. Compare limits, cold starts and which fits bots and APIs.

More in Deploy

See all 33 articles