Skip to content

ERR_PACKAGE_PATH_NOT_EXPORTEDエラーの解決法

問題の概要

Node.js環境でモジュールをインポートしようとした際に、次のようなエラーが発生することがあります:

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './cid' is not defined by "exports"

このエラーは、Node.jsパッケージが**ESモジュール(ESM)**として構成されている場合に、CommonJS方式(require())でサブパスのインポートを試みたときに発生します。

典型的なケースとして、orbit-dbmultiformats パッケージを使用する以下のコード:

javascript
const OrbitDB = require('orbit-db');

を実行すると、次のエラーが報告されます:

text
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './cid' is not defined by "exports" in .../package.json

エラーが発生する主な原因は、multiformats パッケージが v1.0.0以降でESMモジュールに移行したため、CommonJSのrequire()でのインポートがサポートされなくなった点にあります。

エラーメカニズムの本質

Node.jsのpackage.json"exports" フィールドは、外部からアクセス可能なパスを制御します。モジュールがESM形式のみをエクスポートする場合、CommonJSのrequire() でサブパスを読み込もうとするとこのエラーが発生します。

推奨解決策

方法1: orbit-dbのバージョンダウングレード(最速解決法)

最も簡単な解決方法は、orbit-dbのバージョンを0.26.0にダウングレードし、CommonJS互換バージョンを使用することです:

  1. package.json を編集してorbit-dbのバージョンを固定:

    json
    "dependencies": {
      "orbit-db": "^0.26.0"
    }
  2. 依存関係を再インストール:

    bash
    rm -rf node_modules package-lock.json
    npm install

このバージョンでは、multiformatsではなくcidsパッケージを使用しているため、ESM関連の問題が発生しません。

方法2: multiformatsの互換バージョンを明示的にインストール

orbit-dbの最新バージョンを維持する必要がある場合、以下のコマンドでmultiformatsを互換バージョンに固定します:

bash
npm install multiformats@9.9.0

TIP

orbit-db@0.28.7multiformats@10.0.2 を使用しますが、multiformats@9.x はESMモジュールではないため互換性があります。

方法3: ソースコードの修正(アプリケーション改修可能な場合)

モジュール側の修正が可能な場合、動的インポートを使用してESMモジュールを読み込むようにします:

修正前:

javascript
const { CID } = require('multiformats/cid')

修正後:

javascript
let CID;
import('multiformats/cid').then(module => {
  CID = module.CID;
});
// 非同期処理が必要

ただし、この変更はアプリケーションのアーキテクチャが非同期処理に対応している必要があります。

javascript
// CommonJS方式のrequire
const { CID } = require('multiformats/cid');
javascript
// 非同期で動的インポート
const loadCID = async () => {
  const { CID } = await import('multiformats/cid');
  return CID;
};

その他のよくあるケースと解決法

IDEの自動インポートによる不正パス

開発ツールの自動インポート機能が間違ったパスを追加する場合があります:

javascript
// 誤った例: '/index', '/lib' が不要
import { useRef } from 'react/index';
import { getFirestore } from 'firebase-admin/lib/firestore';
javascript
// パッケージルートからのインポート
import { useRef } from 'react';
import { getFirestore } from 'firebase-admin/firestore';

重要

パッケージ提供の正規インポートパスは、package.json"exports"フィールドで定義されています。/index/libのようなサブパスを独自に指定するのは避けましょう。

パッケージ固有のインポート方式変更

file-typeなど特定のパッケージでは、ESM対応のために専用のローダーが必要な場合があります:

javascript
import { loadEsm } from 'load-esm';

const fileType = await loadEsm('file-type').then(module => module.fileType);

ESMとCJSの混在環境では動的インポートが有効ですが、アプリケーション全体の非同期処理設計が必要です。

予防策とベストプラクティス

  1. 依存関係のバージョン互換性確認

    bash
    npm outdated
    npm ls [パッケージ名] # 依存ツリーのチェック
  2. ESM移行時の段階的対応

    json
    {
      "type": "module", // 全面移行時に設定
      "imports": { ... } // カスタムインポート設定
    }
  3. 公式ドキュメント参照

環境変数での回避(一時的対策)

開発中のみの一時的回避策として--openssl-legacy-providerを設定できますが、根本解決ではありません:

json
"scripts": {
  "start": "set NODE_OPTIONS=--openssl-legacy-provider && node app.js"
}

まとめ

ERR_PACKAGE_PATH_NOT_EXPORTEDエラーは、主にESモジュール形式のパッケージをCommonJS方式で読み込もうとした場合に発生します。根本的な解決には以下が効果的です:

  1. 依存パッケージの互換バージョンを使用する(推奨)
  2. アプリケーションをESM仕様に移行する
  3. IDEの自動インポートを監視し、不正パスを修正する

Node.jsのモジュールシステムを理解し、package.json"exports"フィールドを参照することで、このエラーを効果的に回避できます。