“An unexpected error occurred” is the least informative error message of all error messages. It is as if cosmic rays have transformed your predictable computing machinery into a white noise generator.
Startup errors with ASP.NET Core don’t provide much information either, at least not in a production environment. Here are 7 tips for understanding and fixing those errors.
1. There are two types of startup errors.
There are unhandled exceptions originating outside of the Startup class, and exceptions from inside of Startup. These two error types can produce different behavior and may require different troubleshooting techniques.
2. ASP.NET Core will handle exceptions from inside the Startup class.
If code in the ConfigureServices or Configure methods throw an exception, the framework will catch the exception and continue execution.
Although the process continues to run after the exception, every incoming request will generate a 500 response with the message “An error occurred while starting the application”.
Two additional pieces of information about this behavior:
- If you want the process to fail in this scenario, call CaptureStartupErrors on the web host builder and pass the value false.
- In a production environment, the “error occurred” message is all the information you’ll see in a web browser. The framework follows the practice of not giving away error details in a response because error details might give an attacker too much information. You can change the environment setting using the environment variable ASPNETCORE_ENVIRONMENT, but see the next two tips first. You don’t have to change the entire environment to see more error details.
3. Set detailedErrors in code to see a stack trace.
The following bit of code allows for detailed error message, even in production, so use with caution.
4. Alternatively, set the ASPNETCORE_DETAILEDERRORS environment variable.
Set the value to true and you’ll also see a stack trace, even in production, so use with caution.
5. Unhandled exceptions outside of the Startup class will kill the process.
Perhaps you have code inside of Program.cs to run schema migrations or perform other initialization tasks which fail, or perhaps the application cannot bind to the desired ports. If you are running behind IIS, this is the scenario where you’ll see a generic 502.5 Process Failure error message.
These types of errors can be a bit more difficult to track down, but the following two tips should help.
6. For IIS, turn on standard output logging in web.config.
If you are carefully logging using other tools, you might be able to capture output there, too, but if all else fails, ASP.NET will write exception information to stdout by default. By turning the log flag to true, and creating the output directory, you’ll have a file with exception information and a stack trace inside to help track down the problem.
The following shows the web.config file created by dotnet publish and is typically the config file in use when hosting .NET Core in IIS. The attribute to change is the stdoutLogEnabled flag.
Important: Make sure to create the logging output directory.
Important: Make sure to turn logging off after troubleshooting is complete.
7. Use the dotnet CLI to run the application on your server.
If you have access to the server, it is sometimes easier to go directly to the server and use dotnet to witness the exception in real time. There’s no need to turn on logging or set and unset environment variables. With Azure, as an example, I can go to the Kudu website for an app service, open the debug console, and launch the application like so:
There’s a good chance I’ll be able to witness the exception leading to the 502.5 error and see the stack trace. Keep in mind that with many environments, you might be running in a different security context than the web server process, so there is a chance you won’t see the same behavior.
Debugging startup errors in ASP.NET Core is a simple case of finding the exception. In many cases, #7 is the simplest approach that doesn’t require code or environment changes.