できない.dev

Node.js で「Error: Cannot find module」が解消できない

実行ディレクトリと package.json の位置がズレている、依存が未インストール、ESM と CommonJS の切り替えを誤っているの 3 系統が主因。
require.resolve と npm ls で原因を切り分ける。

公開: 更新:

要約

Error: Cannot find module 'foo' の対処は、まず その foo が node の解決経路にあるか を確認することから始める。
原因は概ね 3 系統に分かれる: 実行位置のズレ、依存定義の欠落、モジュールシステムの不一致。
順に切り分ければ大半が片付く。

よくある原因

  1. 作業ディレクトリ違い: npm install した場所と node 起動位置が別で、node_modules が見つからない
  2. 依存欠落: package.json に書かれていない/devDependencies だが NODE_ENV=production で起動している
  3. ESM/CJS の混在: "type":"module" を付けたのに require() を使っている、または ESM で拡張子を省略している
  4. monorepo / workspaces のホイスト: 親側 node_modules に上げられて子パッケージから見えない

解決策

1. 解決経路を可視化する

node -e "console.log(require.resolve('foo'))"

期待しない場所が出れば、NODE_PATH や workspace 構造を疑う。
エラーになる場合はそもそも install されていない。
Node が node_modules を上方向に再帰探索する仕組みは 公式 Modules ドキュメント(新しいタブで開く) に記載されている。

2. 依存の存在確認と追加

npm ls foo
# foo が出なければ
npm install foo

本番モードで起動するなら dependencies に置く。devDependencies だけだと npm ci --omit=dev 環境で消える。

3. ESM / CJS をどちらかに揃える

// package.json: "type":"module"
import foo from "foo";
import { helper } from "./util.js";   // 拡張子必須

CJS のままにするなら "type":"commonjs" に戻し、require() で書く。
混ぜない。

4. workspaces / monorepo の場合

npm install foo --workspace=packages/web

ルートから一括で入れるとホイストの挙動が読みにくいので、対象 workspace を明示すると確実に正しい階層に入る。

実行例

実際に上記の手順を node:20 環境で動かすと、require('./does-not-exist') を含む app.jsError: Cannot find module './does-not-exist'(終了コード 1)で失敗し、その後参照先ファイルを作成して再実行すると loaded: 42 を出力して正常終了(終了コード 0)することが確認できる。

$ node app.js
node:internal/modules/cjs/loader:1210
  throw err;
  ^
 
Error: Cannot find module './does-not-exist'
Require stack:
- /tmp/tmp.f0yPnaCVTg/app.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1207:15)
    at Module._load (node:internal/modules/cjs/loader:1038:27)
    at Module.require (node:internal/modules/cjs/loader:1289:19)
    at require (node:internal/modules/helpers:182:18)
    at Object.<anonymous> (/tmp/tmp.f0yPnaCVTg/app.js:1:1)
    at Module._compile (node:internal/modules/cjs/loader:1521:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1623:10)
    at Module.load (node:internal/modules/cjs/loader:1266:32)
    at Module._load (node:internal/modules/cjs/loader:1091:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:164:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/tmp/tmp.f0yPnaCVTg/app.js' ]
}
 
Node.js v20.20.2
終了コード: 1
$ node -e "console.log('loaded:', require('./does-not-exist.js'))"
loaded: 42
終了コード: 0
$ node -e "console.log(require.resolve('./does-not-exist.js'))"
/tmp/tmp.f0yPnaCVTg/does-not-exist.js

— 2026-08-02 時点の出力

この記事は役立ちましたか?