IIS Failed Request Tracing: Debugging 500 Errors and Slow Requests

A generic 500 page and one line in the event log is a poor starting point for debugging IIS. Failed Request Tracing (FREB) fixes that: it records a full trace of every module decision for requests that match your failure conditions, showing you exactly which module returned the error and why. It is the right tool for 500.19 configuration errors, 500.30 startup failures, slow pages, and rewrite loops.

Enable the tracing feature

FREB is an optional IIS component. On a full GUI install: Server Manager, Add Roles and Features, Web Server (IIS), Health and Diagnostics, and tick Tracing. From PowerShell:

Install-WindowsFeature Web-Http-Tracing

The feature installs the provider and the log infrastructure; it does not start tracing anything until you define a rule.

Create a tracing rule

In IIS Manager, select the site, open Failed Request Tracing, and enable it. Then open Failed Request Tracing Rules, Add Rule, and define:

  • Content to trace: all content, or a specific extension/path (for example *.aspx or /api/*).
  • Failure conditions: status code ranges such as 500-599, or time taken over a threshold such as 30 seconds, or both.

Equivalent command-line setup with appcmd:

appcmd set site "Default Web Site" -traceFailedRequestsLogging.enabled:true
appcmd set config "Default Web Site" -section:system.webServer/tracing/traceFailedRequests /+"[path='*',customAction=500]" /commit:apphost

Traces land in %SystemDrive%\inetpub\logs\FailedReqLogFiles by default, one folder per failed request.

Reading the trace XML

Each failed request produces an XML file (open it in a browser – the XSL stylesheet renders it readably) plus the raw file. The trace is a chronological list of events from every module that touched the request. You are looking for two things:

  • Entries with Level=”Warning” or “Error” – these are the events where a module failed.
  • The GENERAL_SET_RESPONSE_ERROR_STATUS / MODULE_SET_RESPONSE_ERROR_STATUS entries, which record the HTTP status and substatus code (for example 500.19 or 500.30) and name the module that set it.

The last error-level entry before the response is sent is normally your culprit. From the command line you can grep for it:

Select-String -Path "C:\inetpub\logs\FailedReqLogFiles\w3svc1\*.xml" -Pattern "MODULE_SET_RESPONSE_ERROR_STATUS" | Select-Object -First 5

Common failure patterns

SymptomWhat the trace showsFix
500.19CONFIGURATION_ERROR event in the config sectionMalformed web.config or missing section; fix the line reported in the trace
500.30In-process startup failure before modules completeCheck the stdout log and Application event log for the real exception
502.5Process failure in out-of-process hostingThe app crashed on launch; read stdout and fix startup
404.19 / 404.20Request filtering rejected the extensionAdd the extension to the allowed list in Request Filtering
Rewrite loopMultiple URL_REWRITE passes with no terminal matchFix the rewrite rules – add a condition or a stopProcessing flag
Slow requestTime taken exceeds your threshold; one module dominatesIdentify the slow module (often auth or compression) and optimize it

Static files and managed requests

FREB traces the whole pipeline, not just managed code. A slow static-file request shows up in the StaticFileModule events; a rewrite loop shows repeated URL Rewrite passes over the same URL. This is what makes FREB better than application logs alone for IIS-level problems: you see exactly which module spent the time or returned the status, including modules that never touch your application code.

For ASP.NET Core apps specifically, split your debugging: FREB covers everything IIS-side (bindings, rewrite, request filtering, static files), while the app’s own startup failures surface in the stdout log and the Application event log. The classic pairing – a 500.30 in FREB plus a first-chance exception in stdout – resolves most broken first deploys in minutes.

Retention and cleanup

Trace files accumulate fast. Set sane limits up front so a burst of failures cannot fill the disk:

appcmd set config -section:system.webServer/tracing/traceFailedRequestsLogging /maxLogFiles:20 /maxLogFileSizeKB:1024 /directory:"%SystemDrive%\inetpub\logs\FailedReqLogFiles"

That caps the site at 20 trace files of 1 MB each, which is plenty for a debugging session and self-cleaning afterwards. When the investigation is over, disable the rule in IIS Manager or with appcmd – leaving FREB enabled on a busy production site is a classic cause of unexplained disk-full alerts.

Operational notes

  • Tracing has a real cost: every matching request writes XML to disk. Enable FREB only on the site you are debugging, and only for the duration of the investigation.
  • Set sane limits – maximum trace file count and size – so a busy site does not fill the disk while you are away.
  • Disable the rule when you are done. Leaving FREB on in production is a common cause of mysterious disk-full alerts.

FREB turns IIS debugging from guesswork into reading a transcript. Enable the feature, define a narrow rule, reproduce the failure, and read the last error-level event – in most cases the fix is visible within minutes. If you are still choosing where to host the site you will be debugging, compare Windows VPS plans on our table, or check our main site for Windows Server VPS options with full IIS access.

If you want a Windows VPS where you control IIS completely – including Failed Request Tracing – Hostwinds’ Windows VPS plans include full administrative access and unmanaged control of the web server.

Leave a Comment