Node.jsのERR_IMPORT_ATTRIBUTE_MISSINGを直す:JSON importをwithへ更新

結論:Node.jsでJSONをES Modulesとして読むときは、JSONであることを示すimport属性が必要です。static importはwith { type: 'json' }、dynamic importは第2引数に{ with: { type: 'json' } }を指定します。属性なしでERR_IMPORT_ATTRIBUTE_MISSINGになった人や、古いassert構文が失敗する人向けの手順です。

最初に、bundler設定上の想定ではなく、実際にエラーを出したNode.jsの版と最初の失敗行を確認します。自分のコードか依存コードかで対応が変わります。

Node.jsの実行版と失敗箇所を確認し、with構文へ修正して再実行する流れ
JSON importエラーの切り分け
目次

再現用のsettings.json

以下を各例で共通使用します。次の内容をsettings.jsonとして、各例の.mjsファイルと同じディレクトリへ保存します。実測環境はNode.js v24.19.0です。Node.js 22系は未実測なので、公式履歴と手元のminor版を照合してください。

{"service":"brief-demo","retry":3}

属性なしと旧assertが失敗する理由

Node.js公式のエラー説明では、必要なimport属性が欠け、対象モジュールを読み込めない状態がERR_IMPORT_ATTRIBUTE_MISSINGです。JSON importにはtype: 'json'が必要です。

属性なしの例は、Node.js v24.19.0で非ゼロ終了し、ERR_IMPORT_ATTRIBUTE_MISSINGになりました。

import settings from './settings.json';
console.log(settings.retry);

古いimport assertionsの例は、同じ環境で非ゼロ終了し、SyntaxError: Unexpected identifier 'assert'になりました。

import settings from './settings.json' assert { type: 'json' };
console.log(settings.retry);

調査基準日2026年10月5日の現行Node.js v26.10.0公式ESM資料は、Node.js 22.0.0でimport assertionsを削除したと記載しています。旧assertと現行withを混在させません。

1. 実行版と失敗ファイルを確認する

node --version
node -p "process.execPath"
  • Node.jsの版と、実際に呼ばれた実行ファイルのパスを控える
  • 対象が.mjsか、package.jsonに"type": "module"があるか確認する
  • 最初のエラー行が自分のソースかnode_modules内か確認する

"type": "module"はJavaScriptをES Modulesとして扱う設定です。JSONであることを示すwith { type: 'json' }とは別物で、前者があってもimport属性は省略できません。

2. staticとdynamicに合うwith構文へ直す

読み込み方古い・不足した書き方修正後
static importassert { type: 'json' }または属性なしwith { type: 'json' }
dynamic import第2引数なし、またはassertオプション{ with: { type: 'json' } }

static importの修正例です。次をsettings.jsonと同じディレクトリのnode-static-fixed.mjsへ保存します。Node.js v24.19.0で3、終了コード0を確認しました。

import settings from './settings.json' with { type: 'json' };
console.log(settings.retry);

dynamic importでは属性を第2引数に置き、JSONの値はdefaultから取得します。次をsettings.jsonと同じディレクトリのnode-dynamic-fixed.mjsへ保存します。こちらも同環境で3、終了コード0でした。

const module = await import('./settings.json', { with: { type: 'json' } });
console.log(module.default.retry);

Import Attributesが非実験扱いになったのは、Node.js 23.1.0、22.12.0、20.18.3、18.20.5です。「Node.js 20なら全部同じ」とせずminorまで確認します。

3. 依存コードで失敗した場合

最初の失敗行が依存パッケージ内なら、自分のimport文だけ直しても解決しません。対象ライブラリの対応版、変更履歴、公式issueを確認し、ロックファイル方針に沿って更新します。Storybook公式リポジトリにも具体的な報告例がありますが、これは依存側調査の例であり、一般構文の根拠はNode.js公式資料です。

  • ロックファイルを含めて更新結果を再現できるようにする
  • node_modulesを直接恒久編集しない
  • 古いEOL版Node.jsへ無条件に戻さない

4. fsとJSON.parseで読む代替

import属性を使えない事情がある場合は、UTF-8で読み込んで解析できます。Node.js v24.19.0で3、終了コード0を確認しました。

import { readFile } from 'node:fs/promises';
const text = await readFile(new URL('./settings.json', import.meta.url), 'utf8');
const settings = JSON.parse(text);
console.log(settings.retry);

これは非同期なのでawaitが必要です。new URL(..., import.meta.url)は現在のモジュール基準ですが、相対文字列を直接readFileへ渡すと通常はカレントディレクトリ基準です。読取失敗とJSON構文不正は別の例外になるため、必要な境界で処理します。また、importのモジュールキャッシュとは異なり、再読込を避けるなら独自キャッシュが必要です。

5. 同じNode.jsで再確認する

node --version
node node-static-fixed.mjs
node node-dynamic-fixed.mjs

検証環境では順にv24.19.0、3、3でした。修正前と同じNode.js実行ファイルで成功し、終了コード0になったかまで確認します。

よくある質問

Q. ERR_IMPORT_ASSERTION_TYPE_MISSINGと同じですか?
近い原因を示す旧エラーです。公式資料では同エラーはv21.1.0で削除され、ERR_IMPORT_ATTRIBUTE_MISSINGはv21.1.0で追加されています。実行版に合う構文を選びます。

Q. package.jsonをtype: moduleにすれば直りますか?
直りません。モジュール形式の指定とJSONのimport属性は役割が異なります。

Q. Node.js 22でも同じ結果ですか?
この記事の実測はv24.19.0です。公式履歴では22.0.0で旧assertが削除され、22.12.0でImport Attributesが非実験化されています。使用中の22.xで確認してください。

Q. 依存が直るまでnode_modulesを書き換えてよいですか?
恒久対応にはしません。対応版、公式パッチ、package managerの正式なパッチ機能など、再現できる方法を選びます。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次