何が起きたのか
ASP.NET Core アプリを発行して IIS に配置し、URL にアクセスすると、次のエラーが表示されます:
HTTP Error 500.30 - ASP.NET Core app failed to start
ANCM In-Process Start Failure
IIS はページを読み込んでいる — つまり Web サーバー自体は動いています。しかし ANCM(ASP.NET Core モジュール、IIS と .NET ランタイムをつなぐブリッジ)が .NET プロセスへのハンドオフに失敗しました。ブラウザにはほとんど情報が表示されません。本当のエラーはどこか別の場所に隠れています。
このエラーは通常、初回デプロイ直後、.NET バージョンのアップグレード後、または .NET アプリをホストしたことのないサーバーへの移行時に発生します。
手順 1:stdout ログを有効にして実際のエラーを確認する
500.30 ページはラッパーに過ぎません。実際の起動時例外は stdout ログに記録されていますが、デフォルトでは無効になっています。発行済みの web.config を開いて、次の箇所を変更してください:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<aspNetCore processPath="dotnet"
arguments=".\YourApp.dll"
stdoutLogEnabled="true"
stdoutLogFile=".\logs\stdout"
hostingModel="inprocess" />
</system.webServer>
</configuration>
stdoutLogEnabled="true" に設定し、logs フォルダを手動で作成してください — IIS は自動作成しません:
mkdir C:\inetpub\wwwroot\YourApp\logs
アプリプールを再起動して URL にアクセスし、ログファイルを開きます。ランタイムが見つからない場合は次のように表示されます:
The framework 'Microsoft.NETCore.App', version '8.0.0' was not found.
起動時の設定エラーの場合は次のような内容になります:
Unhandled exception. System.InvalidOperationException: Unable to resolve service for type 'IDbContext'
Windows イベントビューアー → Windows ログ → アプリケーション も確認してください。ソースを IIS AspNetCore Module V2 でフィルタリングすると、ログファイルより先に起動時例外が記録されていることがよくあります。
手順 2:よくある原因を確認する
原因 1 — .NET ホスティングバンドルがないまたは不正
新規サーバーで最もよくある原因です。ホスティングバンドルは ASP.NET Core ランタイムと IIS モジュールを一緒にインストールします。これがないと、ANCM がアプリを読み込む先がありません。
インストール済みのランタイムを確認します:
dotnet --list-runtimes
正しくインストールされた .NET 8 環境では、次の 2 行が表示されます:
Microsoft.AspNetCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
何も表示されない、またはバージョンが違う場合は、Microsoft から正しいホスティングバンドルをダウンロードしてインストールしてください。バージョンはアプリのターゲットフレームワークと一致させる必要があります — net8.0 には .NET 7 ではなく .NET 8 のホスティングバンドルが必要です。
インストール後、次のコマンドを実行します:
iisreset
リセットを省略しないでください — IIS はモジュール設定をキャッシュするため、リセットなしでは新しいバンドルを認識しません。
原因 2 — アプリプールが「マネージコードなし」に設定されていない
ASP.NET Core は独自の CLR を管理します。IIS も CLR を読み込もうとすると競合が発生します。IIS マネージャー → アプリケーションプール → 対象プール → 基本設定を開き、.NET CLR バージョンをマネージコードなしに設定してください。
# Or via PowerShell:
Import-Module WebAdministration
Set-ItemProperty IIS:\AppPools\YourAppPool managedRuntimeVersion ""
原因 3 — 起動時にアプリがクラッシュする(設定または DI エラー)
Program.cs での起動時例外 — 不正な接続文字列、設定キーの欠落、DI 登録の失敗 — はすべて 500.30 として表面化します。ANCM は何が問題かを把握できず、プロセスが終了したことしか認識しません。stdout ログまたはイベントビューアーに実際の例外が記録されています。
素早く確認する方法:発行済みフォルダからアプリを直接実行します:
cd C:\inetpub\wwwroot\YourApp
dotnet YourApp.dll
コンソールでクラッシュしますか?それが起動時エラーです。そこで修正してから再発行してください。
原因 4 — ASPNETCORE_ENVIRONMENT が設定されていない
環境固有の設定(シークレット、接続文字列、機能フラグ)を参照するアプリは、ASPNETCORE_ENVIRONMENT が設定されていない場合、起動時にクラッシュします。IIS は自動的に設定しません。アプリプールに直接設定してください:
# PowerShell — set on the app pool level:
$envVars = (Get-WebConfiguration system.applicationHost/applicationPools/add[@name='YourAppPool']/environmentVariables)
$envVars.Add(@{name='ASPNETCORE_ENVIRONMENT'; value='Production'})
Set-WebConfiguration system.applicationHost/applicationPools/add[@name='YourAppPool']/environmentVariables -Value $envVars
または web.config の <aspNetCore> 配下に設定します:
<aspNetCore ...>
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
</environmentVariables>
</aspNetCore>
原因 5 — 32 ビットと 64 ビットの不一致
ビット数の不一致は見落としやすい問題です。アプリプールで32 ビットアプリケーションの有効化が True に設定されていて、64 ビットビルドをデプロイしている場合、ANCM は読み込めません(逆も同様です)。プールの詳細設定を確認し、発行ターゲットと一致させてください。
.NET 6 以降のアプリでは、64 ビットで発行し、プールの 32 ビットは無効のままにしてください。
原因 6 — ファイルのアクセス権限
アプリプールの ID には、アプリフォルダへの読み取り・実行権限と、logs フォルダへの書き込み権限が必要です。既定の ID は IIS AppPool\YourAppPool です。権限エラーはイベントビューアーに「アクセスが拒否されました」として表示されますが、ANCM はいずれにせよ 500.30 を報告します。
icacls "C:\inetpub\wwwroot\YourApp" /grant "IIS AppPool\YourAppPool:(OI)(CI)RX"
icacls "C:\inetpub\wwwroot\YourApp\logs" /grant "IIS AppPool\YourAppPool:(OI)(CI)M"
手順 3:修正を確認する
何かを修正しましたか?実際に解決されたことを確認する方法を示します:
- アプリプールをリサイクルする:
Restart-WebAppPool -Name YourAppPool - サイトにアクセスする — 500.30 ページの代わりにアプリが表示されるはずです
- stdout ログで Kestrel の起動行を確認する:
Now listening on: http://localhost:PORT - 既知の API エンドポイントやページにアクセスして、アプリがリクエストを処理していることを確認する
正常に動作したら、stdout ログを無効にしてください:web.config で stdoutLogEnabled="false" に設定します。本番環境でオンのままにしておくと、リクエストごとにログエントリが書き込まれ、実際のトラフィックがある場合は数時間でディスクがいっぱいになる可能性があります。
得られた教訓
500.30 は常に起動時の失敗です — アプリは単一のリクエストも処理する機会がありませんでした。ケースの 90% は 2 つのことに起因します:新規サーバーへのホスティングバンドルの欠落、または最初から dotnet YourApp.dll を直接実行していれば明らかだったはずの起動時例外です。
問題が発生してからではなく、初回デプロイの前に stdout ログを有効にしてください。そして IIS を向ける前に、発行フォルダから dotnet YourApp.dll をテストしてください — このひと手間で、フィードバックループが数分から数秒に短縮されます。

