Fix 'HTTP Error 500.30 - ANCM In-Process Start Failure' When Deploying ASP.NET Core to IIS

intermediate๐ŸชŸ Windows2026-06-03| Windows Server 2016/2019/2022, IIS 10+, ASP.NET Core 3.1 / .NET 5 / .NET 6 / .NET 7 / .NET 8

Error Message

HTTP Error 500.30 - ASP.NET Core app failed to start ANCM In-Process Start Failure
#iis#aspnet-core#windows-server#dotnet

What Happened

You publish your ASP.NET Core app, drop it on IIS, browse to the URL, and get hit with this:

HTTP Error 500.30 - ASP.NET Core app failed to start
ANCM In-Process Start Failure

IIS loads the page โ€” so the web server itself is alive. But ANCM (the ASP.NET Core Module, IIS's bridge to the .NET runtime) couldn't hand off to the .NET process. The browser gives you almost nothing to work with. The real error is hiding somewhere else.

This usually hits right after a first-time deploy, after a .NET version upgrade, or when moving to a server that's never hosted .NET apps before.

Step 1: Turn On stdout Logging to See the Real Error

The 500.30 page is a wrapper. The actual startup exception is in the stdout log โ€” but it's disabled by default. Open your published web.config and flip this:

<?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>

Set stdoutLogEnabled="true" and create the logs folder yourself โ€” IIS won't do it:

mkdir C:\inetpub\wwwroot\YourApp\logs

Restart the app pool, hit the URL, then open the log file. A missing runtime shows up like this:

The framework 'Microsoft.NETCore.App', version '8.0.0' was not found.

A startup config error looks more like:

Unhandled exception. System.InvalidOperationException: Unable to resolve service for type 'IDbContext'

Also check Windows Event Viewer โ†’ Windows Logs โ†’ Application. Filter by source IIS AspNetCore Module V2 โ€” startup exceptions often land there even before the log file does.

Step 2: Check the Most Common Causes

Cause 1 โ€” Missing or Wrong .NET Hosting Bundle

The #1 cause on fresh servers. The Hosting Bundle installs the ASP.NET Core runtime and the IIS module together. Without it, ANCM has nothing to load your app into.

Check what's installed:

dotnet --list-runtimes

A correctly installed .NET 8 environment shows both lines:

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]

Nothing there, or the wrong version? Download and install the correct Hosting Bundle from Microsoft. The version must match your app's target framework โ€” net8.0 needs the .NET 8 Hosting Bundle, not .NET 7.

After installing, run:

iisreset

Don't skip the reset โ€” IIS caches module configs and won't pick up the new bundle without it.

Cause 2 โ€” App Pool Not Set to "No Managed Code"

ASP.NET Core manages its own CLR. If IIS is also trying to load one, you get a conflict. Open IIS Manager โ†’ Application Pools โ†’ your pool โ†’ Basic Settings, and set .NET CLR Version to No Managed Code.

# Or via PowerShell:
Import-Module WebAdministration
Set-ItemProperty IIS:\AppPools\YourAppPool managedRuntimeVersion ""

Cause 3 โ€” App Crashes During Startup (Configuration or DI Error)

Startup exceptions in Program.cs โ€” bad connection string, missing config key, DI registration failure โ€” all surface as 500.30. ANCM doesn't know what went wrong; it just sees the process die. The stdout log or Event Viewer will have the actual exception.

A quick way to confirm: run the app directly from the published folder:

cd C:\inetpub\wwwroot\YourApp
dotnet YourApp.dll

Console crash? That's your startup error. Fix it there, then republish.

Cause 4 โ€” ASPNETCORE_ENVIRONMENT Not Set

Apps that pull from environment-specific config โ€” secrets, connection strings, feature flags โ€” crash during startup when ASPNETCORE_ENVIRONMENT isn't set. IIS doesn't configure it automatically. Set it directly on the app pool:

# 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

Or set it in web.config under <aspNetCore>:

<aspNetCore ...>
  <environmentVariables>
    <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
  </environmentVariables>
</aspNetCore>

Cause 5 โ€” 32-bit vs 64-bit Mismatch

Bitness mismatch is easy to overlook. If the app pool has Enable 32-bit Applications set to True and you're deploying a 64-bit build, ANCM can't load it โ€” or vice versa. Check the pool's Advanced Settings and match it to your publish target.

For .NET 6+ apps, publish 64-bit and keep 32-bit disabled on the pool.

Cause 6 โ€” File Permissions

The app pool identity needs read/execute on the app folder and write on the logs folder. The default identity is IIS AppPool\YourAppPool. Permission failures show up in Event Viewer as "Access is denied" โ€” but ANCM still reports 500.30 either way.

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"

Step 3: Verify the Fix

Fixed something? Here's how to confirm it actually worked:

  • Recycle the app pool: Restart-WebAppPool -Name YourAppPool
  • Browse to the site โ€” you should see your app instead of the 500.30 page
  • Check the stdout log for the Kestrel startup line: Now listening on: http://localhost:PORT
  • Hit a known API endpoint or page to confirm the app is handling requests

Once it's working, disable stdout logging: set stdoutLogEnabled="false" in web.config. Left on in production, it writes a log entry per request and can fill a disk in hours on any real traffic.

Lessons Learned

500.30 is always a startup failure โ€” the app never got a chance to handle a single request. Ninety percent of cases come down to two things: missing Hosting Bundle on a fresh server, or a startup exception that would have been obvious if you'd run dotnet YourApp.dll directly first.

Enable stdout logging before the first deploy, not after things break. And test dotnet YourApp.dll from the publish folder before pointing IIS at it โ€” that one step cuts the feedback loop from minutes to seconds.

Related Error Notes