技術ログ

ERR_INVALID_PACKAGE_CONFIG の正体は、3バイトのBOMだった

公開: 2026-08-19 · 著者: GRAMSHIFT

空に見えるのに空ではない。lsで見えるのはサイズ3という数字だけ

ERR_INVALID_PACKAGE_CONFIG の正体は、3バイトのBOMだった

ホームディレクトリで node を動かしたら、身に覚えのないエラーが出ました。

Error: Invalid package config C:\Users\<ユーザー名>\package.json
    at Object.getNearestParentPackageJSON (node:internal/modules/package_json_reader)
  code: 'ERR_INVALID_PACKAGE_CONFIG'

そこにプロジェクトは置いていません。npm init をした覚えもありません。それでも require() を含むスクリプトが軒並み落ちます。

中身を見たら、3バイトしかなかった

まずファイルの大きさを見ます。

$ ls -la ~/package.json
-rw-r--r-- 1 user 3 Aug 16 02:20 /c/Users/<ユーザー名>/package.json

3バイト。 中身を16進で見ると、正体が分かりました。

$ xxd ~/package.json
00000000: efbb bf                                  ...

EF BB BFUTF-8 の BOM(Byte Order Mark)です。つまりこのファイルは空ではなく、BOMだけが入っている状態でした。JSONとしては当然パースできません。

ここが分かりにくいところで、cat で開いても何も見えず、エディタでも空に見えます。「空っぽに見えるのに壊れている」ので、中身を疑う発想になりにくいのです。サイズが 0 ではなく 3 であることだけが手がかりでした。

なぜホームディレクトリのファイルが、あちこちを壊すのか

Node.js はモジュールを解決するとき、カレントディレクトリから親をたどって最も近い package.json を探します。プロジェクト直下に無ければ、その上、さらに上、と登っていきます。

つまりホームディレクトリに壊れた package.json が1つあると、その配下で動かすスクリプトすべてが、自分のディレクトリに package.json を持たない限り巻き込まれます。エラーメッセージにはホームのパスが出ているのに、動かしているのは別の場所のスクリプト——という状況になり、原因の場所と症状の場所が一致しません。

どこから来たのか

作成日時を見ると、数日前の深夜でした。心当たりは PowerShell です。Windows PowerShell 5.1 では、リダイレクトや Out-File が既定で BOM付きで書き出します。空文字列を書き込むと、中身が無いのに BOM だけのファイルができます。

# これで「3バイトのファイル」ができる
"" | Out-File package.json

おそらく、何かのコマンドが空の出力をリダイレクトした結果です。作った瞬間はエラーが出ないので、数日後にまったく別の作業で踏むことになります。

なお、PowerShell 5.1 の既定エンコーディングそのものが引き起こす文字化けについては、PowerShell の Set-Content で日本語 UTF-8 ファイルが壊れる話にまとめてあります。今回の3バイトのファイルは、その仕様の副産物です。

直し方

正しい package.json をそこに置く必要はありません。そもそも要らないファイルなので、退避してから消すのが確実です。

$ cp ~/package.json /tmp/package.json.bak   # 念のため退避
$ rm ~/package.json
$ node -e "console.log(typeof require('path').join)"
function                                     # 直った

もしそこに本当に package.json が必要なら、BOM無しのUTF-8で書き直します。PowerShell 5.1 なら Set-Content -Encoding utf8 でも BOM が付くので、BOM無しにしたいときは .NET の WriteAllText を使うのが確実です。

同じ形のエラーを見分ける

この件は「JSONが壊れている」という一言でまとめられがちですが、実際には次の3つは別物です。

  • サイズ0 — 完全に空。多くのツールは「空だから既定値」と扱ってくれることがある
  • BOMだけ(3バイト) — 空に見えるが中身がある。JSONパーサは必ず落ちる
  • BOM + 正しいJSON — 見た目は正常。パーサによって通ったり落ちたりする(これがいちばん厄介)

設定ファイルが理由なく壊れているときは、ls でサイズを見て、0でも期待どおりでもない中途半端な数字なら16進で開く。それだけで数十分は節約できます。

持ち帰れる形にすると

  • ERR_INVALID_PACKAGE_CONFIG は「そのパスの package.json が JSON として読めない」という意味。プロジェクトの外を指していることもある。
  • Node はカレントから親をたどって package.json を探すので、ホームに壊れた1つがあると配下が全部巻き込まれる。
  • 3バイトのファイルは BOM だけを疑うEF BB BF)。空に見えて空ではない。
  • PowerShell 5.1 の書き出しは既定で BOM 付き。空の出力をリダイレクトすると壊れたファイルが生まれる。
  • 要らない設定ファイルなら、直すより退避して消すほうが速くて確実。

よくある質問

ERR_INVALID_PACKAGE_CONFIG はどういう意味のエラー?

エラーメッセージに書かれているパスの package.json が、JSONとして読めないという意味です。構文エラーのほか、中身がBOMだけといったケースも含みます。注意点として、そのパスは作業中のプロジェクトとは限りません。Nodeはカレントディレクトリから親をたどって最も近い package.json を探すため、ホームディレクトリなど上位に壊れたファイルがあると、その配下すべてで同じエラーが出ます。

中身が空に見える package.json が壊れているのはなぜ?

UTF-8のBOM(EF BB BF)だけが入っている可能性が高いです。テキストとしては何も表示されませんが3バイトのデータがあり、JSONパーサは先頭でつまずきます。lsでサイズが0ではなく3になっているのが手がかりで、xxdやhexdumpで開くと確認できます。Windows PowerShell 5.1 は既定でBOM付きで書き出すため、空の出力をリダイレクトすると簡単に生まれます。

ホームディレクトリの package.json は消してよい?

そこにNodeプロジェクトを作った覚えがないなら、消して構いません。念のため別の場所へコピーしてから削除し、node -e で require が通ることを確認してください。もし必要なファイルであれば、BOM無しのUTF-8で書き直します。PowerShell 5.1 では Set-Content -Encoding utf8 でもBOMが付くため、BOM無しが必要なときは .NET の WriteAllText を使うのが確実です。