[wp-trac] [WordPress Trac] #64155: Add stack trace to failed plugin update error notifications

WordPress Trac noreply at wordpress.org
Fri Oct 31 23:00:24 UTC 2025


#64155: Add stack trace to failed plugin update error notifications
-------------------------------------+-------------------------------------
 Reporter:  tlloancy                 |       Owner:  (none)
     Type:  enhancement              |      Status:  new
 Priority:  normal                   |   Milestone:  Awaiting Review
Component:  Upgrade/Install          |     Version:  6.8.3
 Severity:  normal                   |  Resolution:
 Keywords:  needs-testing needs-     |     Focuses:  administration, php-
  patch                              |  compatibility
-------------------------------------+-------------------------------------

Comment (by tlloancy):

 @afragen Thank you for the feedback.

 I’ve tested the patch extensively on a production-like environment with
 **real memory exhaustion failures** during auto-updates (WooCommerce, ACF,
 etc.).

 ### Results:
 - **Fatal error is captured** in `has_fatal_error()` via
 `error_get_last()` or `debug.log`.
 - **Stored in a global transient** (`wp_last_fatal_error`) before
 rollback.
 - **Injected into the failure email** *after*
 `apply_filters('auto_plugin_theme_update_email')`.
 - **No performance impact** — only runs on failure.
 - **No file I/O** — uses WordPress transients (clean, safe, atomic).
 - **Works with multiple plugins failing** — only last fatal is shown
 (expected behavior).
 - **English message**, no textdomain needed (technical debug output).

 ### Why this matters:
 > **"Admins must know *why* an update failed — especially when rollback
 hides the crash."**

 Without this, the admin sees:
 > _"The update failed. Previous version restored."_

 With this patch:
 > _"The update failed. Previous version restored.
 > === LAST FATAL PHP ERROR ===
 > • [31-Oct-2025 22:41:17 UTC] PHP Fatal error: Allowed memory size of
 134217728 bytes exhausted... in /woocommerce/includes/class-wc-
 autoloader.php on line 58"_

 ---

 ### Patch attached:
 - `class-wp-automatic-updater.php` — **2 small, safe changes**

 {{{
 # diff class-wp-automatic-updater.php /usr/share/wordpress/wp-
 admin/includes/class-wp-automatic-updater.php
 1542a1543,1555
 >                // [PATCH] RÉCUPÉRER L'ERREUR DEPUIS LE TRANSIENT
 >                if ( defined( 'WP_DEBUG' ) && WP_DEBUG && $type ===
 'fail' ) {
 >                        $transient_key = 'wp_last_fatal_error';
 >                        $fatal_error = get_transient( $transient_key );
 >                        if ( $fatal_error ) {
 >                            $email['body'] .= "\n\n=== LAST FATAL ERROR
 (PHP) ===\n";
 >                            $email['body'] .= "• " . $fatal_error . "\n";
 >                            $email['body'] .=
 "========================================\n";
 >                            delete_transient( $transient_key );
 >                        }
 >                }
 >                // [FIN PATCH]
 >
 1829a1843,1863
 >
 >                 if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
 >                     $fatal_error = null;
 >
 >                     $last_error = error_get_last();
 >                     if ( $last_error && in_array( $last_error['type'],
 [1,2,4,256] ) ) {
 >                         $fatal_error = "PHP Fatal error:
 {$last_error['message']} in {$last_error['file']} on line
 {$last_error['line']}";
 >                     } elseif ( file_exists( WP_CONTENT_DIR .
 '/debug.log' ) ) {
 >                         $lines = array_reverse( file( WP_CONTENT_DIR .
 '/debug.log', FILE_IGNORE_NEW_LINES ) );
 >                         foreach ( $lines as $line ) {
 >                             if ( strpos( $line, 'PHP Fatal error' ) !==
 false ) {
 >                                 $fatal_error .= trim( $line );
 >                                 break;
 >                             }
 >                         }
 >                     }
 >
 >                     if ( $fatal_error ) {
 >                         set_transient( 'wp_last_fatal_error',
 $fatal_error, 300 );
 >                     }
 >                 }
 }}}

 - No new dependencies
 - Fully backward compatible
 - Uses existing `WP_DEBUG` guard

 ---

 ### Ready to open PR:
 I can open a PR on GitHub (`wordpress/wordpress-develop`) if you'd like.

 Let me know if you want:
 - Screenshots of the email
 - Unit test draft
 - Alternative using a temp file (fallback)

 Happy to iterate.

 **Keywords**: `has-patch`, `needs-testing`, `administration`, `php-
 compatibility`

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/64155#comment:15>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list