Opened 4 weeks ago
Last modified 10 days ago
#64256 new enhancement
Add HTTP 500 status code for WordPress critical error messages
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | 7.0 | Priority: | normal |
| Severity: | normal | Version: | |
| Component: | Bootstrap/Load | Keywords: | has-patch changes-requested |
| Focuses: | Cc: |
Description
Summary
Ensure HTTP 500 status code is always returned for WordPress critical error messages
Component
Bootstrap/Load (or Site Health)
Description
Currently, when WordPress displays the critical error message "There has been a critical error on this website.", it does not consistently return an HTTP status code. While the documentation mentions that fatal errors "typically" return HTTP 500, there is no guarantee that monitoring systems can reliably detect these errors.
Problem
Monitoring tools cannot reliably detect WordPress critical errors because:
- No HTTP status code is guaranteed to be returned
- The response may appear as HTTP 200 (success) to monitoring systems
- Critical errors go undetected until manual inspection
- Existing documentation mentions "typically 500" but doesn't guarantee monitoring-friendly behavior
Related Tickets
Related to ticket #44458 (WSOD - White Screen of Death) which addresses error handling improvements.
Proposed Solution
Ensure that WordPress always sets HTTP status code 500 when displaying critical error messages, regardless of whether a custom php-error.php template exists or not. This ensures:
- Monitoring systems can automatically detect critical errors
- HTTP status codes correctly reflect the error state
- Standard HTTP error handling works as expected
- Consistent behavior across all WordPress installations
Implementation Options
Option 1: Always set HTTP 500
Modify _default_wp_die_handler() in wp-includes/functions.php to always set HTTP status code 500 when displaying critical error messages, even if headers were already sent.
Option 2: Filter/Feature Flag
Add an optional filter force_500_on_fatal_error that allows forcing HTTP status code 500 for fatal errors, ensuring backward compatibility while enabling monitoring-friendly behavior.
Option 3: Ensure php-error.php sets status code
Document and ensure that custom php-error.php templates should set HTTP status codes, and provide a default implementation that always sets 500.
Current Behavior
class-wp-fatal-error-handler.phpsets'response' => 500in args (line 212)_default_wp_die_handler()callsstatus_header($parsed_args['response'])(line 3884)- However, this only works if
!did_action('admin_head')and headers haven't been sent - Custom
php-error.phptemplates may not set status codes
Testing
Tested scenarios:
- cURL to verify HTTP status code:
curl -I https://example.com/test-fatal-error.php - Browser developer tools to check response headers
- Monitoring systems to verify error detection
- Cases where headers were already sent
Backward Compatibility
This change should be backward compatible:
- Only affects HTTP status codes, not error messages
- Doesn't change existing error handling logic
- Can be implemented as opt-in via filter if needed
Use Case
Monitoring systems rely on HTTP status codes to detect server errors. Currently, WordPress critical errors may not return HTTP 500, causing:
- False negatives in monitoring alerts
- Delayed detection of critical issues
- Inconsistent error reporting
References
- WordPress documentation mentions fatal errors "typically" return HTTP 500
- Related to ticket #44458 (WSOD improvements)
- Monitoring systems require reliable HTTP status codes for error detection
Attachments (2)
Change History (8)
#2
@
4 weeks ago
Thank you for the feedback! You're absolutely right on both points. I've updated the patch to address these issues.
Changes Made
- Removed Redundant String Checks: The patch now uses a single, language-independent method instead of checking multiple strings.
- Language-Independent Solution: Instead of string matching (which fails with translations), the patch now:
- Checks for error code
'internal_server_error'- This is the code used by WordPress fatal error handler (seeclass-wp-fatal-error-handler.phpline 238) - Also checks
$parsed_args['code']- In case the code is set there instead - Ensures HTTP 500 if response is already 500 - Covers cases where the fatal error handler already set it
Why This Works
- Language-independent: Error code
'internal_server_error'is always the same, regardless of language - Uses WordPress internals: The fatal error handler creates WP_Error with this exact code
- Covers all cases: Checks both WP_Error code and parsed_args code
- No redundancy: Single, clear check
The updated patch is attached.
#4
@
3 weeks ago
- Keywords has-patch changes-requested added
- Milestone changed from Awaiting Review to 7.0
This makes sense to me.
Using this sample plugin code, for example:
<?php add_action( 'init', function () { non_existing_function(); } );
I get a 200 OK response, unexpectedly, even though PHP is dumping out:
Fatal error: Uncaught Error: Call to undefined function non_existing_function()
@swissky Can you open a pull request to facilitate collaboration and automated checks?
Hi there, welcome back to WordPress Trac! Thanks for the ticket.
Looking at the patch, checking if the message contains either
critical errororThere has been a critical errorseems redundant, as the first one should suffice. But more importantly, how would this work for messages translated into other languages?