Skip to content

Instantly share code, notes, and snippets.

@vapvarun
Created June 4, 2026 03:11
Show Gist options
  • Select an option

  • Save vapvarun/fb27c12ebb832ebd5d10d6f84a2cbcb3 to your computer and use it in GitHub Desktop.

Select an option

Save vapvarun/fb27c12ebb832ebd5d10d6f84a2cbcb3 to your computer and use it in GitHub Desktop.
Capture PHP fatal errors on WordPress shutdown with logging and Slack alert - tweakswp.com tutorial
<?php
/**
* Capture fatal errors on WordPress shutdown
*
* WordPress catches many errors through WP_Error and wp_die(), but PHP-level
* fatal errors (E_ERROR, E_PARSE) kill the script before any WordPress handler
* can run. register_shutdown_function() is the only way to intercept them.
*
* Tutorial: https://tweakswp.com/
*/
/**
* Fatal error handler registered with PHP's shutdown mechanism.
*
* Writes fatal error details to a persistent log file and optionally
* sends an alert to a Slack webhook.
*/
function tweakswp_fatal_error_handler(): void {
$error = error_get_last();
if ( ! $error ) {
return;
}
// Only act on errors that killed the script. Warnings and notices
// are handled by the standard WP_DEBUG / error_log path.
$fatal_types = [ E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR ];
if ( ! in_array( $error['type'], $fatal_types, true ) ) {
return;
}
$message = sprintf(
'[%s] FATAL: %s in %s:%d',
gmdate( 'Y-m-d H:i:s' ),
$error['message'],
$error['file'],
$error['line']
);
// 1. Write to a dedicated fatal log (outside the webroot if possible).
$log_file = WP_CONTENT_DIR . '/fatal-errors.log';
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
file_put_contents( $log_file, $message . PHP_EOL, FILE_APPEND | LOCK_EX );
// 2. Optional: POST to a Slack webhook.
// Only runs if the cURL extension is loaded — no WordPress helpers available.
$webhook_url = defined( 'TWEAKSWP_SLACK_WEBHOOK' ) ? TWEAKSWP_SLACK_WEBHOOK : '';
if ( $webhook_url && extension_loaded( 'curl' ) ) {
$ch = curl_init( $webhook_url );
curl_setopt_array( $ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode( [ 'text' => $message ] ),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => [ 'Content-Type: application/json' ],
] );
curl_exec( $ch );
curl_close( $ch );
}
}
// Register as early as possible — ideally in an mu-plugin so it covers
// fatal errors that occur before plugins finish loading.
register_shutdown_function( 'tweakswp_fatal_error_handler' );
// Define the webhook URL in wp-config.php:
// define( 'TWEAKSWP_SLACK_WEBHOOK', 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL' );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment