Closed rogerfar closed 5 years ago
Is the error page still rendered? We intentionally avoid re-running Startup in this case until the app is restarted. If you want us to continue attempting to run startup, you can disable capturing startup errors by calling .CaptureStartupErrors(false)
on your WebHostBuilder
.
I used .CaptureStartupErrors(false)
and this morning the site was up this morning, so that seems to have solved it.
The error page was just the standard error:
An error occurred while starting the application. .NET Core 4.6.27414.05 X64 v4.0.0.0 | Microsoft.AspNetCore.Hosting version 2.2.0-rtm-35687 | Microsoft Windows 10.0.14393 | Need help?
I realized that my WebHostBuilder is wrapped in a try catch:
try
{
Log.Information("Starting host");
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
config.AddJsonFile("appsettings.json", false, false);
})
.CaptureStartupErrors(false)
.UseIISIntegration()
.UseSerilog()
.Build()
.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
Where Log is the Serilog logger, but is supposed to log the database, which is unavailable..
How does CaptureStartupErrors
behave with the Application Initialization
feature in IIS? I'm just wondering what the attempt to start interval would be.
CaptureStartupErrors stops the process from crashing when there's an Exception thrown during the execution of the methods in your Startup
method, and instead renders a simple error page with the error message (in development mode).
As a result, when CaptureStartupErrors
is on, the flow is something like this:
If the client makes another request, it goes through to the server ASP.NET Core set up to render the error page, so IIS doesn't think anything is wrong.
When CaptureStartupErrors
is off, the flow is like this:
Now, if the client makes another request, the underlying ASP.NET Core app isn't running so IIS starts it up again and keeps hitting the error.
Application Initialization (as far as I know, I'm not an IIS expert ;)) just configures IIS to make a request back to itself (at the path you specify) to "prime" your application before letting clients access the app. So, when CaptureStartupErrors
is on, the IIS Application Initialization feature seems to get in a loop constantly thinking the app is failing to start (because the captured startup error just keeps causing a 500).
If you're using Application Initialization, I'd suggest one of two paths forward:
Disable CaptureStartupErrors
. As long as you're monitoring logs and stack traces from your application, you'll get the startup errors through that so you don't really need this feature anyway
Add retry logic for expected or transient failures during startup (like database access)
I'm going to close this issue because there isn't anything we plan to fix here, but feel free to ask further questions if you need clarification!
Thanks @anurse for the write up!
Just as note for who sees this in the future, I'm using Application Initialization` due to hangfire tasks that run in the background.
I'm going to add a self-check mechanism that attempts restarting the app.
Thanks!
This was helpful. However, even after I added .CaptureStartupErrors(false)
my app was still getting permanently stuck with a HTTP Error 500.30 - ANCM In-Process Start Failure
page.
In my case there are some global config files that our app references that aren't there in the image when its starting up, but are put in place further on in the server provisioning process.
My solution was just to recycle the app pool once the script runs that puts those file in place:
Restart-WebAppPool APIPool -ErrorAction SilentlyContinue
That seems to have done the trick.
We have some test servers that reboot themselves every night. The web server reboots but it up before the SQL server is up. The .NET Core 2.2 application gets automatically started with the "Application Initialization" feature in IIS.
When the application starts automatically it runs some initialization in the Startup.cs Configure method. But because the database is unreachable an exception is thrown:
When this happens the application stays unreachable, forever, until you manually restart the site + app pool.
Every time you try to access the app you get:
But the log files don't record anything, nor the event viewer.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
When the application fails to initialize it should retry to initialize every time it's requested.