Skip to content

Fix overly specific exception catching in Runner.php#6209

Open
Copilot wants to merge 5 commits intomainfrom
copilot/fix-specific-exception-handling
Open

Fix overly specific exception catching in Runner.php#6209
Copilot wants to merge 5 commits intomainfrom
copilot/fix-specific-exception-handling

Conversation

Copy link
Contributor

Copilot AI commented Jan 25, 2026

Fix overly specific exception catching in Runner.php

Plan:

  • Explore repository structure and understand the issue
  • Modify Runner.php to catch all exceptions (not just WP_CLI\Iterators\Exception)
  • Add Behat feature test to verify general exceptions are caught
  • Run linting, code style checks, and static analysis - all passing
  • Verify the fix manually with test script - confirmed working
  • Update to pass exception object for better error context
  • Code review and security check - both passed

Issue Summary:
Currently, Runner::run_command() only catches WP_CLI\Iterators\Exception. Other exceptions bubble up to WordPress's error handler and display a generic fatal error instead of proper WP-CLI error output.

Solution:
Changed the catch block to catch all \Throwable types and pass the full exception object to WP_CLI::error() so they are properly transformed to WP-CLI error messages with exception class context.

Changes Made:

  1. Modified php/WP_CLI/Runner.php to catch \Throwable instead of Exception
  2. Changed to pass entire exception object to WP_CLI::error() instead of just the message
  3. Removed unused import of WP_CLI\Iterators\Exception
  4. Added Behat test scenario to features/runner.feature to verify exception handling
  5. Updated test expectations to include exception class name in output

Tests & Verification:

  • ✅ Linting (composer lint) - passed
  • ✅ Code style (composer phpcs) - passed
  • ✅ Static analysis (composer phpstan) - passed
  • ✅ Manual testing confirms output now includes exception class:
    • Error: Exception: Test exception message
    • Error: RuntimeException: Test runtime exception message
  • ✅ Backward compatible with Iterator exceptions

Example Output:
Before: Error: Test exception message
After: Error: Exception: Test exception message

Original prompt

This section details on the original issue you should resolve

<issue_title>Runner.php is catching overly specific exception?</issue_title>
<issue_description>## Bug Report

Describe the current, buggy behavior

It seems like Runner.php catches only a very specific exception type.

When a command is executed, the only exceptions that are caught and transformed to STDERR outputs are exceptions of type WP_CLI\Iterators\Exception.

Other exceptions bumble up to the global WordPress fatal error handler and will go through wp_die and display the default fatal error message:

There has been a critical error on this website.Learn more about troubleshooting WordPress. There has been a critical error on this website.

In PHPStorm I could not find any places where WP_CLI\Iterators\Exception is thrown beside in Query.php.

Is this behaviour intentional? I would expect that wp-cli transforms uncaught exceptions to STDERR output at some point.

Describe how other contributors can replicate this bug

WP_CLI::add_command('foo', function () {
    throw new \Exception('foo message');
});
wp foo

Describe what you expect as the correct outcome

I would expect to see the following terminal output:

Error: foo message

And a log message written to the default configuration using error_log

Let us know what environment you are running this on

Shell:  /bin/zsh
PHP binary:     /usr/local/Cellar/php@7.4/7.4.28_1/bin/php
PHP version:    7.4.28
php.ini used:   /usr/local/etc/php/7.4/php.ini
MySQL binary:   /usr/local/bin/mysql
MySQL version:  mysql  Ver 8.0.28 for macos11.6 on x86_64 (Homebrew)
SQL modes:      ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
WP-CLI root dir:        phar://wp-cli.phar/vendor/wp-cli/wp-cli
WP-CLI vendor dir:      phar://wp-cli.phar/vendor
WP_CLI phar path:       /Users/calvinalkan
WP-CLI packages dir:    /Users/calvinalkan/.wp-cli/packages/
WP-CLI global config:   
WP-CLI project config:  
WP-CLI version: 2.6.0

</issue_description>

Comments on the Issue (you are @copilot in this section)

@danielbachhuber @calvinalkan @johnbillion Would either of you like to put together a pull request with your suggested changes?

Catching exceptions thrown by commands seems helpful to me, although WP-CLI remains the last mechanism to catch the exception.

WP-CLI has a custom wp_die_handler we may be able to improve in some way:

wp-cli/php/utils-wp.php

Lines 86 to 104 in 0b22dee

function replace_wp_die_handler() {
\remove_filter( 'wp_die_handler', '_default_wp_die_handler' );
\add_filter(
'wp_die_handler',
function() {
return __NAMESPACE__ . '\\wp_die_handler';
}
);
}
function wp_die_handler( $message ) {
if ( $message instanceof \WP_Error ) {
$message = $message->get_error_message();
}
$message = wp_clean_error_message( $message );
WP_CLI::error( $message );
}


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Changed catch block in Runner::run_command() from catching only
WP_CLI\Iterators\Exception to catching all Throwable types. This ensures
that exceptions thrown by commands are properly transformed to WP-CLI
error messages instead of bubbling up to WordPress's error handler.

Also added Behat test to verify the fix works correctly.

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix overly specific exception handling in Runner.php Fix overly specific exception catching in Runner.php Jan 25, 2026
Copilot AI requested a review from swissspidy January 25, 2026 17:19
@codecov

This comment was marked as resolved.

This comment was marked as resolved.

swissspidy and others added 2 commits January 25, 2026 12:39
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@swissspidy

This comment was marked as resolved.

gemini-code-assist[bot]

This comment was marked as resolved.

@swissspidy

This comment was marked as resolved.

Instead of passing just the exception message, now passing the entire
exception object. This causes WP_CLI::error_to_string() to prepend the
exception class name to the error message, providing users with more
context about what type of exception was thrown.

Updated Behat tests to match the new expected output format.

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>

This comment was marked as resolved.

@swissspidy swissspidy marked this pull request as ready for review February 3, 2026 15:02
@swissspidy swissspidy requested a review from a team as a code owner February 3, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runner.php is catching overly specific exception?

2 participants