エラー
Could not load file or assembly 'Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The system cannot find the file specified.
ビルドは成功する。アプリはクラッシュする。これが最も腹立たしい点だ — これはコンパイル時ではなく、ランタイムの障害だ。IDEは本番環境でクラッシュする前に一切警告を出してくれない。
根本原因
CLR(Common Language Runtime)はアセンブリをロードする際、バージョンの完全一致を要求する。マイナーバージョンひとつ違うだけでも処理を中断する。原因は主に3つだ:
- バージョンの不一致: あるパッケージが
Newtonsoft.Json 12.0.0.0を参照しているが、出力ディレクトリに実際に配置されているのは13.0.0.0だ。CLRはバージョン12を探し、13を見つけ、ロードを拒否する。 - DLLの欠落: アセンブリが出力フォルダや発行フォルダにコピーされていない — 依存関係としてスキップされたか、発行時にトリミングされた。
- バインドリダイレクトの不正: .NET Frameworkアプリは
app.configやweb.configの<bindingRedirect>を使って「バージョン12でもよい、13を使え」と指示する。リダイレクトがない、または誤っている場合、ランタイムはここで終了する。
修正1:NuGetパッケージを復元する
十中八九、gitからのプルやブランチの切り替えによってローカルのパッケージキャッシュが壊れている。他の対処の前にまずここから始めよう。
# プロジェクトまたはソリューションディレクトリ内で
dotnet restore
# または NuGet CLI を使う場合
nuget restore YourSolution.sln
その後、リビルドする:
dotnet build --configuration Release
DLLが実際に出力先に配置されているか確認する:
dir bin\Release\net6.0\Newtonsoft.Json.dll
ここにDLLがなければ、クラッシュするのは当然だ。他の対処を行う前に、コピーの手順を修正すること。
修正2:バインドリダイレクトを追加または修正する(.NET Framework)
.NET Frameworkでは、ランタイムはバージョンの不一致を解決するために App.config または Web.config を使用する。ファイルを開き、<runtime> セクションを探す。障害が発生しているアセンブリのバインドリダイレクトがなければ追加する:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json"
publicKeyToken="30ad4fe6b2a6aeed"
culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0"
newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
13.0.0.0 の部分は実際にインストールされているバージョンに置き換えること。以下で確認できる:
dotnet list package | findstr Newtonsoft
XMLを手動編集したくない場合は、Visual Studioで自動生成できる。ツール → NuGet パッケージ マネージャー → ソリューションの NuGet パッケージの管理 を開き、バージョンを統一すれば、設定ファイルを自動で書き直してくれる。
修正3:プロジェクト間でパッケージバージョンを統一する
複数プロジェクトのソリューションでは問題が複雑になる。ProjectAは Newtonsoft.Json 12.0.3 を使い、ProjectBは 13.0.3 を使っている。ランタイムでは、どちらかのバージョンが「負け」て欠落し、CLRがエラーを出す。
まずソリューション全体の参照を洗い出す:
# PowerShell — プロジェクト全体の Newtonsoft.Json 参照を検索
Get-ChildItem -Recurse -Filter "*.csproj" | Select-String "Newtonsoft.Json"
次に、すべてを同一バージョンに固定する:
dotnet add package Newtonsoft.Json --version 13.0.3
恒久的な解決策として、Directory.Packages.props ファイル(中央パッケージ管理)を使用してソリューション全体でバージョンを一元管理する:
<!-- Directory.Packages.props -->
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>
その後、すべての .csproj から Version="..." を削除する — バージョンは中央ファイルから継承される。設計上、バージョンのばらつきは起こり得なくなる。
修正4:出力ディレクトリへのコピーを強制する
DLLがNuGetキャッシュに存在するにもかかわらず、ビルド出力に反映されないことがある。.csproj 内に、ランタイムへのコピーを妨げる ExcludeAssets や PrivateAssets フラグがないか確認する:
<PackageReference Include="Newtonsoft.Json" Version="13.0.3">
<!-- ランタイムを妨げる ExcludeAssets や PrivateAssets は削除する -->
</PackageReference>
NuGet経由ではなく直接アセンブリを参照している場合は、Private を true に設定してビルドのたびにコピーされるようにする:
<Reference Include="Newtonsoft.Json">
<HintPath>..\libs\Newtonsoft.Json.dll</HintPath>
<Private>true</Private>
</Reference>
修正5:NuGetキャッシュをクリアする
キャッシュが壊れていると、まさにこのような幽霊現象が発生する — パッケージはインストール済みに見えるが、出力に配置されるDLLが誤っていたり不完全だったりする。キャッシュを完全に削除してやり直す:
# すべての NuGet キャッシュをクリア
dotnet nuget locals all --clear
# クリーンな状態で復元
dotnet restore
修正6:発行プロファイルを確認する
エラーがローカル開発では発生せず、発行後にのみ現れる場合は、発行プロファイルがアセンブリをトリミングしている可能性が高い。明示的に無効化する:
# トリミングなしの自己完結型発行
dotnet publish -c Release --self-contained true -r win-x64 /p:PublishTrimmed=false
または Properties/PublishProfiles/*.pubxml の発行プロファイルを開き、アプリが実行時に必要とするアセンブリに対して PublishTrimmed が true になっていないことを確認する。
検証
修正後は、実際に解決されたか確認する — 思い込みは禁物だ:
- リビルド:
dotnet build -c Release - 出力に正しいバージョンのDLLがあるか確認する:
dir bin\Release\**\Newtonsoft.Json.dll /s - アプリを実行してエラーが消えていることを確認する。
- バインドリダイレクトを使用する.NET Frameworkアプリの場合は、Fusion Log Viewer(
fuslogvw.exe、Windows SDKに付属)を使用する。ログを有効化してエラーを再現し、ログエントリを読む — アセンブリの検索シーケンス全体が表示され、誤ったリダイレクトを数秒で特定できる。
# Fusion Log Viewer を起動
fuslogvw.exe
予防策
- 中央パッケージ管理により、複数プロジェクトのソリューションでバージョンのばらつきが完全になくなる。propsファイルひとつ、真実のソースはひとつ、予期せぬ問題はゼロ。
- 定期的な監査: 定期的に
dotnet list package --outdatedを実行する。推移的な依存関係のギャップは、10バージョン遅れるより2バージョン遅れの段階で対処する方がはるかに簡単だ。 - CIでは浮動バージョンを禁止する — 本番ビルドで
*や13.*は使わない。特定のバージョンに固定し、意図的に更新する。 - .NETがビルド出力と一緒に生成する
*.deps.jsonや他のJSONマニフェストを調査する際は、ToolCraftのJSON Formatterを使えば、IDEを立ち上げることなく構造を検証・探索できる。

