'Cannot find module' e 'ModuleNotFoundError' no deploy

O runtime tentou importar um módulo e não o encontrou, porque o pacote não está instalado ou o caminho está errado. Leia o nome do módulo na mensagem e confira dependências, caminho, maiúsculas e extensão.

Atualizado em 7 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Diferenciar um pacote ausente de um caminho de arquivo errado
  • Corrigir as versões Node.js e Python do erro passo a passo
  • Evitar que o erro volte no próximo deploy
Nesta página

A sua aplicação iniciava sem problema no seu computador, você fez o deploy e o log termina com uma destas mensagens:

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'

As duas dizem a mesma coisa: um import ou require citou algo que o runtime não conseguiu localizar. A correção quase nunca é misteriosa, mas você precisa ler a mensagem antes de chutar. O nome entre aspas diz em qual de duas famílias de problema você está.

Cannot findmodule 'x'leia o nome'express'nome puroestá no package.json?só em devDependencies?a instalação rodou?'./utils'caminhoo arquivo foi enviado?maiúsculas iguais?extensão .js (ESM)?saída do build?
O nome entre aspas decide o ramo: pacote puro aponta para as dependências, caminho aponta para o arquivo.

O que esses erros significam de fato?#

No Node.js, o require() lança MODULE_NOT_FOUND quando o caminho ou o pacote não existe. A versão com ES modules, o import, lança ERR_MODULE_NOT_FOUND. No Python, ModuleNotFoundError é uma subclasse de ImportError, lançada quando um módulo não pôde ser localizado (documentação do Python).

Esta é a forma em ES modules, para um pacote ausente e para um arquivo relativo:

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"?

Repare no formato do nome:

  • Um nome puro (express, discord): um pacote que não está instalado onde a aplicação roda.
  • Um caminho (./utils, /app/utils): um arquivo que o runtime não achou naquele local exato.

Tudo abaixo segue essa divisão.

O pacote está faltando nas dependências?#

É a causa mais comum. Para um nome de pacote puro, o Node.js começa na pasta do arquivo atual, procura em node_modules e sobe pelas pastas pai até a raiz do sistema de arquivos (documentação do Node.js). Se nenhuma node_modules nesse caminho tiver o pacote, vem o erro.

Confira nesta ordem:

  1. Ele está no package.json? Se você instalou com npm install express, ele está listado. Se copiou código de um tutorial e nunca instalou, não está.
  2. Ele está só em devDependencies? O npm diz que dependencies é para pacotes de runtime e devDependencies é para ferramentas de que os usuários do seu módulo não precisam, como frameworks de teste e transpiladores (documentação do npm). Uma instalação de produção pode pular os pacotes de desenvolvimento, e o npm ci os omite por padrão quando NODE_ENV é production (documentação do npm). Se a aplicação importa o pacote em runtime, mova-o:
bash
npm install --save-prod express
  1. A instalação rodou mesmo no servidor? Enviar a node_modules do seu PC não é confiável. Envie o package.json mais o lockfile e instale a partir deles.

O npm ci é o comando certo para uma instalação limpa. Ele exige um package-lock.json existente, apaga qualquer node_modules que já esteja lá e sai com erro, em vez de atualizar o lockfile, quando o package.json e o lockfile não batem. Esse último comportamento ajuda: transforma uma divergência silenciosa numa falha visível.

bash
npm ci
node index.js

Se o npm ci falhar porque o lockfile está fora de sincronia, rode npm install localmente, faça commit do lockfile atualizado e faça o deploy de novo.

O caminho, as maiúsculas ou a extensão estão errados?#

Quando o nome é um caminho, a causa é um arquivo que não está onde o import diz.

Maiúsculas e minúsculas. No Linux, ./Utils.js e ./utils.js são dois arquivos diferentes. Os sistemas de arquivos do Windows e do macOS costumam ignorar essa diferença, então um import com a caixa errada funciona na sua máquina e falha no servidor. Renomeie o arquivo ou corrija o import para que fiquem idênticos. Se você mudar só a caixa do nome de um arquivo, confira se o seu cliente Git registrou a mudança, porque algumas configurações a ignoram.

Extensão ausente em ES modules. Com import, especificadores relativos precisam da extensão, e índices de diretório têm de ser escritos por completo (documentação de ESM do Node.js). Isto funciona com require em CommonJS, mas não com import:

js
// Falha num ES module: ERR_MODULE_NOT_FOUND
import { helper } from "./utils";

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

A sua aplicação é um ES module quando o package.json tem "type": "module" ou o arquivo termina em .mjs. Se você usa TypeScript com um bundler localmente, imports sem extensão podem funcionar ali e quebrar quando você roda a saída diretamente.

Um arquivo que nunca foi enviado. Confira se o arquivo está no seu ZIP ou no seu commit. Os culpados comuns são uma linha do .gitignore ou um upload que pulou uma pasta. Num monorepo, um pacote compartilhado que fica fora da pasta publicada também vai faltar.

O arquivo principal ou a saída do build estão errados?#

Alguns projetos compilam para uma pasta dist ou build. Se o comando de início aponta para dist/index.js e a etapa de build nunca rodou, ou a dist está ignorada no controle de versão, o próprio ponto de entrada some:

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

Confirme três coisas: o comando de build roda antes do start, a pasta de saída faz parte do que você publica (ou é gerada no servidor) e o arquivo principal na sua configuração bate com o caminho real. Confira também o "main" no package.json se você importa o pacote pelo nome, porque um main ausente ou que não resolve, sem um index.js, faz o módulo inteiro aparecer como ausente (documentação do Node.js).

Por que o Python diz "No module named"?#

A versão Python tem as próprias causas.

O pacote não está instalado. Instale e registre, para que o próximo ambiente também o receba:

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

Depois, no destino, python -m pip install -r requirements.txt. A documentação do pip descreve esse fluxo de freeze e depois install, e também avisa que o pip freeze não calcula um lockfile nem o resultado de um resolvedor (documentação do pip). Para fixar tudo de verdade, use uma ferramenta de lockfile.

O nome do import é diferente do nome de instalação. Isso confunde muita gente:

Você escreve Você instala
import yaml PyYAML
import PIL Pillow
import cv2 opencv-python
import dotenv python-dotenv
import discord discord.py

Interpretador errado. pip e python podem pertencer a instalações diferentes. Use python -m pip install ... para o pacote ir para o interpretador que vai rodar o seu código. Dentro de um ambiente virtual, ative-o primeiro.

Um arquivo local esconde ou não acha o módulo. Um arquivo chamado discord.py ou random.py no seu projeto pode esconder o pacote verdadeiro. Para os seus próprios módulos, confira se a estrutura de pastas bate com o import e se você roda a aplicação a partir do diretório de trabalho esperado.

Como diagnosticar rápido?#

Comece pela mensagem:

  1. Copie o nome exato do módulo do log.
  2. Nome puro? Rode npm ls express (Node.js) ou python -m pip show discord.py (Python) no mesmo ambiente que roda a aplicação.
  3. Caminho? Liste a pasta e compare o nome caractere por caractere, incluindo maiúsculas e extensão.
  4. Ainda travado? Rode o import que falha isoladamente:
bash
node -e "require.resolve('express')"
node --input-type=module -e "await import('express')"
python -c "import discord; print(discord.__file__)"

O require.resolve lança MODULE_NOT_FOUND quando não acha o módulo, então mostra o que o runtime enxerga sem iniciar a aplicação inteira.

Mais um caso do Node.js: o require() só consegue carregar um ES module se ele não tiver await no nível superior; caso contrário, lança ERR_REQUIRE_ASYNC_MODULE (documentação do Node.js). É outro erro, mas aparece no mesmo lugar. Nessa situação, troque por import().

Como evitar que ele volte?#

  • Trate o lockfile como parte do código: faça commit do package-lock.json e use npm ci nas instalações.
  • Mantenha os pacotes de runtime em dependencies.
  • Dê nomes em minúsculas aos arquivos e importe com a mesma grafia exata.
  • Em ES modules, escreva sempre a extensão.
  • Fixe os pacotes Python no requirements.txt e instale com o mesmo interpretador que roda a aplicação.
  • Teste localmente o formato publicado: apague a node_modules, rode npm ci e inicie a aplicação. Se falhar aí, vai falhar no servidor.

Para outras falhas de deploy, veja como ler erros de build, como ler os logs da sua aplicação e como hospedar uma aplicação Node.js.

Como fazer isso na Square Cloud#

Na Square Cloud você faz o deploy enviando um ZIP, pela CLI, com push no GitHub ou pela extensão do VS Code. Qualquer que seja a escolha, a primeira verificação é a mesma: abra os logs em tempo real, copie o nome do módulo do erro e compare com os arquivos que você realmente enviou. No start, a plataforma roda npm install quando não existe node_modules, com NODE_ENV=production: um pacote que está só em devDependencies não é instalado e gera esse erro.

O gerenciador de arquivos no navegador mostra os arquivos da sua aplicação, então você confirma se o caminho do erro existe e se as maiúsculas batem. O editor salva direto na aplicação, sem redeploy.

Se o erro cita o seu arquivo de entrada, confira se a configuração do arquivo principal aponta para um arquivo que existe. Essa configuração fica no squarecloud.app, que é opcional: o painel pode gerá-lo no deploy (runtime, memória, arquivo principal), ou você pode escrevê-lo na raiz do projeto. Não há etapa de build, então uma entrada em dist exige enviar a pasta já compilada ou colocar o build no comando de início.

Com a correção pronta localmente, envie com o comando commit da CLI ou com push no GitHub pela GitHub Action oficial, que pode rodar commit --restart a cada push. O passo a passo está na página da CLI.

Deploy

Envie pelo GitHub, pela CLI ou em ZIP e publique em segundos

Saiba mais

Perguntas frequentes

Qual a diferença entre MODULE_NOT_FOUND e ERR_MODULE_NOT_FOUND?

MODULE_NOT_FOUND é o código que o Node.js define quando o require() (CommonJS) não resolve um caminho. ERR_MODULE_NOT_FOUND é o código da mesma falha com import (ES modules). As causas se sobrepõem, mas os ES modules também exigem a extensão completa em imports relativos.

Por que minha aplicação funciona no meu PC mas dá 'Cannot find module' depois do deploy?

A sua máquina tem arquivos e pacotes que a cópia publicada não tem: um pacote instalado globalmente, uma pasta node_modules que você nunca envia, um pacote que só está em devDependencies ou um arquivo com maiúsculas diferentes. O Linux trata Utils.js e utils.js como arquivos diferentes; Windows e macOS normalmente não.

ModuleNotFoundError significa que eu devo rodar pip install?

Normalmente sim, mas confira o nome do pacote antes. O nome do import e o nome de instalação costumam ser diferentes: import yaml vem de PyYAML, import PIL de Pillow, import cv2 de opencv-python. Confirme também que o pip instala no mesmo interpretador Python que roda a sua aplicação.

Devo enviar a pasta node_modules?

Não. Envie o package.json e o lockfile e instale no destino com npm ci ou o comando equivalente do seu gestor de pacotes. Uma node_modules montada em outro sistema operacional pode conter binários que não rodam em outro lugar.

Próximo artigoServerless ou container: qual usar para bots e APIsServerless executa funções por requisição e escala a zero; container mantém um processo sempre ligado. Veja limites, cold start e qual serve para bots e APIs.