マガジン

Node.jsで「Cannot find module」が出たとき:AI生成コードの原因を順に確かめる

AIを使いこなす

Claudeで執筆し、GPTで自動校閲・修正しています。

手がフォルダ構成のメモとファイルを照合している静物
記事の内容をもとに制作したAI生成イメージです。実際の製品画面や検証結果の写真ではありません。

AIが書いたコードを動かして「Cannot find module」が出たら、まずエラー文の引用符の中を見てください。代表的な確認先は、次の3つです。 • 'express' のように ./ で始まらない名前なら、パッケージが入っていない可能性が高いです。 • './utils' や '../lib/db' のようにパスなら、ファイルの場所・名前・拡張子を疑います。 • パスも名前も合っていそうなら、CommonJS(require)とESM(import)の違いを見ます。パッケージが公開していない場所を読むと、通常は別のエラーコード ERR_PACKAGE_PATH_NOT_EXPORTED になります。 この記事では、この見分け方を早見表にし、最後にAIへ質問するときの依頼文も載せます。なお、本文のエラー文やコードは説明用の例で、実際に実行した出力ではありません。Nodeのバージョンによって文面は変わることがあるので、引用符の中身と「どのファイルから読もうとしたか」に注目してください。

この記事の目次
  1. 1. エラー文のどこを見るか
  2. 2. 原因別の早見表
  3. 3. モジュール形式の違いで起きるもの
  4. 4. 調べる順番(3分チェック)
  5. 5. AIへの伝え方
  6. 6. それでも直らないとき

1. エラー文のどこを見るか

次のような出力を想定します(説明用の例)。

Error: Cannot find module 'express'
Require stack:
- /home/user/app/server.js

読む場所は2つです。

  1. 引用符の中:探している名前です。
  2. Require stack(または "imported from" の後):その名前を書いているファイルです。AIに見せるときも、ここは必ず含めます。

Node.jsの公式ドキュメントでは、require() は相対パス(./ ../)と、先頭に付かない名前(bare specifier)を区別して解決すると説明されています。相対パスは読み込む側のファイルの場所が基準で、名前だけの指定は node_modules フォルダを上の階層へたどりながら探します(Node.js: Modules (CommonJS))。引用符の中が名前なのかパスなのかで、調べる場所が分かれるのはこのためです。

2. 原因別の早見表

  • express など名前、疑う原因:未インストール、確認コマンド(macOS/Linux):ls node_modules/express、直し方:npm install express
  • 同上、package.json にも無い、疑う原因:AIが依存関係を書き忘れた、確認コマンド(macOS/Linux):cat package.json、直し方:入れたうえで package.json に載ったか確認
  • 同上、入っているのに出る、疑う原因:実行場所が違う/別フォルダの node_modules、確認コマンド(macOS/Linux):pwd と ls、直し方:package.json のあるフォルダへ移動して実行
  • ./utils などパス、疑う原因:ファイル名・場所の違い、確認コマンド(macOS/Linux):ls(対象フォルダ)、直し方:実在する名前・場所に合わせる
  • ./utils(ESMの import)、疑う原因:拡張子の省略、確認コマンド(macOS/Linux):ファイル冒頭が import か確認、直し方:./utils.js と拡張子を書く
  • ERR_PACKAGE_PATH_NOT_EXPORTED、疑う原因:パッケージが公開していない場所、確認コマンド(macOS/Linux):各パッケージの package.json の exports、直し方:公開されている入口から読む

Windowsでは ls を dir、cat を type、node_modules/express を node_modules\express に読み替えてください。

未インストールの場合

node_modules に該当フォルダが無ければ、入れるだけです。AIが提示したコマンドの npm install 名前 をそのまま実行する前に、パッケージ名が実在するかも確認してください。AIは存在しない名前や似た名前を出すことがあり、見知らぬ名前を入れるのは安全面でも避けたいところです。公式サイトやnpmの公開ページで、名前と提供元を確かめてからにしましょう。

パス・拡張子の場合

相対パスは、実行したフォルダではなく、require や import を書いたファイルの位置が基準です(前掲のModulesドキュメント)。AIが「src/ の中のファイル」を前提にパスを書いたのに、実際は別の階層に置いていた、というずれがよく起こります。大文字小文字の違いも、環境によって通ったり通らなかったりするので、ファイル名と完全に一致させてください。

3. モジュール形式の違いで起きるもの

ここが「パスは合っているのに出る」ケースの本命です。公式ドキュメントによると、CommonJSの require は拡張子を省略でき、.js .json .node の順に探します。フォルダを指定すれば index.js なども探します。一方ESMの import では、相対・絶対指定に拡張子が必須で、./dir/ のようなディレクトリindexの省略もできません(Node.js: ECMAScript modules)。

つまり、AIがCommonJSの感覚で書いた次のコードを、ESMとして動かすと失敗します(説明用の例)。

js
// app.mjs(ESMとして扱われる)
import { add } from './utils';      // 拡張子なし → 見つからない
import { add } from './utils.js';   // こう書く

NodeがファイルをESMとCommonJSのどちらで扱うかは、明示指定があればそれに従います。.mjs と最も近い package.json の "type": "module" はESM、.cjs と "type": "commonjs" はCommonJSです。明示指定がない .js の扱いはNode.jsのバージョンによって異なり、現行版では import export などの構文から判定されます(Node.js: ECMAScript modules、Node.js: Packages)。

確認手順はシンプルです。package.json に "type": "module" があるか、ファイル拡張子が .mjs か .cjs かを見てください。AIのコードが require なのに "type": "module" だったり、逆に import なのに type 未指定だったりしたら、形式の食い違いです。どちらかに統一します。

補足:require と ESM の組み合わせ

Node.js 22以降の公式ドキュメントでは、require() で同期的なESM(トップレベル await を含まないもの)を読み込めると説明されています。トップレベル await を含む場合は ERR_REQUIRE_ASYNC_MODULE となり、import() を使うよう案内されています(Modules (CommonJS))。古いNodeでは同じ書き方が通らない可能性があるため、node -v の結果は必ずAIに伝えてください。

補足:公開されていない場所を読んでいる

パッケージの package.json に exports があると、書かれていない内部パスは読み込めず、ERR_PACKAGE_PATH_NOT_EXPORTED が出ます(Node.js: Packages)。これは「Cannot find module」とは別のエラーです。pkg/dist/internal.js のような深いパスをAIが書いていたら、READMEにある公開用の読み込み方に直します。

4. 調べる順番(3分チェック)

  1. 引用符の中が名前か、パスかを見る。
  2. node -v と pwd を確認する。
  3. 名前なら ls node_modules/名前 と cat package.json。
  4. パスなら、Require stack に出たファイルを開いて、指定先が実在するか ls で確認する。
  5. import と require の混在、"type"、拡張子を見る。
  6. それでも解決しなければ、次の依頼文でAIに渡す。

5. AIへの伝え方

「エラーが出ました、直して」だけでは、AIは推測で別のコードを書きがちです。次の形で、事実を分けて渡してください。

Node.jsで次のエラーが出ました。原因の候補を可能性の高い順に3つ挙げ、
それぞれ確認用のコマンドを示してください。まだコードは書き換えないでください。

【環境】node -v の結果:v22.x(実際の値に置き換え)/OS:(例)macOS
【実行コマンド】node server.js
【エラー全文】
(Require stack を含めて貼る)
【package.json】
(dependencies と "type" の部分)
【該当ファイルの先頭10行】
(import / require の行を含める)
【フォルダ構成】
(ls の結果)

回答に出た確認コマンドは、自分で実行して結果をAIに返してください。AIが「入っているはず」と言っても、ls node_modules/名前 の結果が事実です。

渡す前に、APIキーやパスワード、社内のフォルダ名やユーザー名は伏せ字にしてください。.env の中身は貼らないでください。エラー文のパスには自分のユーザー名が含まれることがあります。

6. それでも直らないとき

  • node_modules を消して npm install し直す方法は有効なことが多いですが、package.json の内容が間違っていれば同じ結果になります。先に中身を確認してください。
  • AIが一度に複数ファイルを書き換えた場合は、直前の動いていた状態に戻して、1つずつ試してください。
  • エラー文の引用符の中が、毎回同じ名前でなく変わっていく場合は、順番に依存関係が足りていない可能性があります。AIに「このファイルが読み込んでいる名前を全部列挙して」と頼み、package.json と突き合わせると早く片づきます。

出典・参考資料