From c3116bc8730a5262b49d9a8a41855523204e83b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:05:36 +0000 Subject: [PATCH 01/14] Initial plan From d683f7cecf4bb0a6f13ca0773d1c6e64c255e5fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:11:13 +0000 Subject: [PATCH 02/14] Add HTTP error handling to wp core check-update command Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/core-check-update.feature | 13 ++++++++ src/Core_Command.php | 50 +++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/features/core-check-update.feature b/features/core-check-update.feature index 32ede965..791ac9c7 100644 --- a/features/core-check-update.feature +++ b/features/core-check-update.feature @@ -70,3 +70,16 @@ Feature: Check for more recent versions """ --- """ + + Scenario: Check update shows warning when version check API fails + Given a WP install + And that HTTP requests to `api.wordpress.org` will respond with: + """ + HTTP/1.1 500 Internal Server Error + """ + + When I run `wp core check-update --force-check` + Then STDERR should contain: + """ + Warning: Failed to check for updates + """ diff --git a/src/Core_Command.php b/src/Core_Command.php index b9bbb2b4..d9fccf65 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -31,6 +31,13 @@ */ class Core_Command extends WP_CLI_Command { + /** + * Stores HTTP API errors encountered during version check. + * + * @var \WP_Error|null + */ + private $version_check_error = null; + /** * Checks for WordPress updates via Version Check API. * @@ -93,7 +100,17 @@ public function check_update( $args, $assoc_args ) { ); $formatter->display_items( $updates ); } else { - WP_CLI::success( 'WordPress is at the latest version.' ); + // If there was an HTTP error during version check, show a warning + if ( $this->version_check_error ) { + WP_CLI::warning( + sprintf( + 'Failed to check for updates: %s', + $this->version_check_error->get_error_message() + ) + ); + } else { + WP_CLI::success( 'WordPress is at the latest version.' ); + } } } @@ -1439,8 +1456,18 @@ private function get_download_url( $version, $locale = 'en_US', $file_type = 'zi */ private function get_updates( $assoc_args ) { $force_check = Utils\get_flag_value( $assoc_args, 'force-check' ); + + // Reset error tracking + $this->version_check_error = null; + + // Hook into HTTP API debug to capture errors during version check + add_action( 'http_api_debug', [ $this, 'capture_version_check_error' ], 10, 5 ); + wp_version_check( [], $force_check ); + // Remove the hook after version check + remove_action( 'http_api_debug', [ $this, 'capture_version_check_error' ], 10 ); + /** * @var object{updates: array}|false $from_api */ @@ -1496,6 +1523,27 @@ private function get_updates( $assoc_args ) { return array_values( $updates ); } + /** + * Handles the http_api_debug action to capture HTTP errors during version check. + * + * @param array|WP_Error $response HTTP response or WP_Error object. + * @param string $context Context of the HTTP request. + * @param string $class HTTP transport class name. + * @param array $args HTTP request arguments. + * @param string $url URL being requested. + */ + private function capture_version_check_error( $response, $context, $class, $args, $url ) { + // Only capture errors for the version check API + if ( false === strpos( $url, 'api.wordpress.org/core/version-check' ) ) { + return; + } + + // Store the error if the response is a WP_Error + if ( is_wp_error( $response ) ) { + $this->version_check_error = $response; + } + } + /** * Clean up extra files. * From c0445e4ffb571c758b6708f7b9489e9c34bf8fa8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:13:37 +0000 Subject: [PATCH 03/14] Add context check to capture_version_check_error method Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- composer.json | 6 ++++++ src/Core_Command.php | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/composer.json b/composer.json index 6a3fe712..a9016041 100644 --- a/composer.json +++ b/composer.json @@ -79,5 +79,11 @@ }, "support": { "issues": "https://github.com/wp-cli/core-command/issues" + }, + "repositories": { + "self": { + "type": "path", + "url": "." + } } } diff --git a/src/Core_Command.php b/src/Core_Command.php index d9fccf65..44f67ab4 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -1538,6 +1538,11 @@ private function capture_version_check_error( $response, $context, $class, $args return; } + // Only capture on response, not pre_response + if ( 'response' !== $context ) { + return; + } + // Store the error if the response is a WP_Error if ( is_wp_error( $response ) ) { $this->version_check_error = $response; From ce80b88accf700fae52c2708748806a021ac4ed4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:14:09 +0000 Subject: [PATCH 04/14] Revert accidental composer.json changes --- composer.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/composer.json b/composer.json index a9016041..6a3fe712 100644 --- a/composer.json +++ b/composer.json @@ -79,11 +79,5 @@ }, "support": { "issues": "https://github.com/wp-cli/core-command/issues" - }, - "repositories": { - "self": { - "type": "path", - "url": "." - } } } From 301cfd209d7eb52bb48506e7f068fd5aac6119cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:17:17 +0000 Subject: [PATCH 05/14] Address code review feedback: add try-finally, use str_contains, clarify unused params Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Core_Command.php | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Core_Command.php b/src/Core_Command.php index 44f67ab4..59af8a78 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -1463,10 +1463,12 @@ private function get_updates( $assoc_args ) { // Hook into HTTP API debug to capture errors during version check add_action( 'http_api_debug', [ $this, 'capture_version_check_error' ], 10, 5 ); - wp_version_check( [], $force_check ); - - // Remove the hook after version check - remove_action( 'http_api_debug', [ $this, 'capture_version_check_error' ], 10 ); + try { + wp_version_check( [], $force_check ); + } finally { + // Ensure the hook is always removed, even if wp_version_check() throws an exception + remove_action( 'http_api_debug', [ $this, 'capture_version_check_error' ], 10 ); + } /** * @var object{updates: array}|false $from_api @@ -1526,15 +1528,23 @@ private function get_updates( $assoc_args ) { /** * Handles the http_api_debug action to capture HTTP errors during version check. * + * This method signature matches the http_api_debug action hook signature. + * Note: $class and $args parameters are not used but are required by the hook. + * * @param array|WP_Error $response HTTP response or WP_Error object. * @param string $context Context of the HTTP request. - * @param string $class HTTP transport class name. - * @param array $args HTTP request arguments. + * @param string $_class HTTP transport class name (unused). + * @param array $_args HTTP request arguments (unused). * @param string $url URL being requested. */ - private function capture_version_check_error( $response, $context, $class, $args, $url ) { - // Only capture errors for the version check API - if ( false === strpos( $url, 'api.wordpress.org/core/version-check' ) ) { + private function capture_version_check_error( $response, $context, $_class, $_args, $url ) { + // Only capture errors for the version check API using str_contains for PHP 8.0+ + // or fallback to strpos for older versions + $is_version_check_url = function_exists( 'str_contains' ) + ? str_contains( $url, 'api.wordpress.org/core/version-check' ) + : false !== strpos( $url, 'api.wordpress.org/core/version-check' ); + + if ( ! $is_version_check_url ) { return; } From fec81ec92d83bafde23bcd85f821f23bc25a46a6 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 3 Dec 2025 11:56:05 +0100 Subject: [PATCH 06/14] Lint fix --- src/Core_Command.php | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/Core_Command.php b/src/Core_Command.php index 59af8a78..6b444c31 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -99,18 +99,16 @@ public function check_update( $args, $assoc_args ) { [ 'version', 'update_type', 'package_url' ] ); $formatter->display_items( $updates ); - } else { + } elseif ( $this->version_check_error ) { // If there was an HTTP error during version check, show a warning - if ( $this->version_check_error ) { - WP_CLI::warning( - sprintf( - 'Failed to check for updates: %s', - $this->version_check_error->get_error_message() - ) - ); - } else { - WP_CLI::success( 'WordPress is at the latest version.' ); - } + WP_CLI::warning( + sprintf( + 'Failed to check for updates: %s', + $this->version_check_error->get_error_message() + ) + ); + } else { + WP_CLI::success( 'WordPress is at the latest version.' ); } } @@ -1537,14 +1535,8 @@ private function get_updates( $assoc_args ) { * @param array $_args HTTP request arguments (unused). * @param string $url URL being requested. */ - private function capture_version_check_error( $response, $context, $_class, $_args, $url ) { - // Only capture errors for the version check API using str_contains for PHP 8.0+ - // or fallback to strpos for older versions - $is_version_check_url = function_exists( 'str_contains' ) - ? str_contains( $url, 'api.wordpress.org/core/version-check' ) - : false !== strpos( $url, 'api.wordpress.org/core/version-check' ); - - if ( ! $is_version_check_url ) { + public function capture_version_check_error( $response, $context, $_class, $_args, $url ) { + if ( false !== strpos( $url, 'api.wordpress.org/core/version-check' ) ) { return; } From 55a17887204eea1872cded9e2df68c5a100336e7 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 20 Jan 2026 11:22:54 +0100 Subject: [PATCH 07/14] Update src/Core_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Core_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core_Command.php b/src/Core_Command.php index f603be6f..4a6265bf 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -1545,7 +1545,7 @@ private function get_updates( $assoc_args ) { * @param string $url URL being requested. */ public function capture_version_check_error( $response, $context, $_class, $_args, $url ) { - if ( false !== strpos( $url, 'api.wordpress.org/core/version-check' ) ) { + if ( false === strpos( $url, 'api.wordpress.org/core/version-check' ) ) { return; } From 49deb6666d26f0d2bd7dcdea9eea484927ab9570 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:38:43 +0000 Subject: [PATCH 08/14] Fix HTTP mock in test to use full URL with protocol and path Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/core-check-update.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/core-check-update.feature b/features/core-check-update.feature index 791ac9c7..1e069b17 100644 --- a/features/core-check-update.feature +++ b/features/core-check-update.feature @@ -73,7 +73,7 @@ Feature: Check for more recent versions Scenario: Check update shows warning when version check API fails Given a WP install - And that HTTP requests to `api.wordpress.org` will respond with: + And that HTTP requests to https://api.wordpress.org/core/version-check/1.7/ will respond with: """ HTTP/1.1 500 Internal Server Error """ From 9ac0295eaeaf8676cb895ce799101552bf463a97 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sun, 25 Jan 2026 09:58:50 -0500 Subject: [PATCH 09/14] Update src/Core_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Core_Command.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Core_Command.php b/src/Core_Command.php index 05dc9415..7f13160b 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -1559,9 +1559,11 @@ public function capture_version_check_error( $response, $context, $_class, $_arg return; } - // Store the error if the response is a WP_Error + // Store the error if the response is a WP_Error; clear it otherwise. if ( is_wp_error( $response ) ) { $this->version_check_error = $response; + } else { + $this->version_check_error = null; } } From 447a740f4349bfbbb82c1605596d2efa0e878305 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sun, 25 Jan 2026 10:18:08 -0500 Subject: [PATCH 10/14] Fix error response --- features/core-check-update.feature | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/core-check-update.feature b/features/core-check-update.feature index 1e069b17..48bfe303 100644 --- a/features/core-check-update.feature +++ b/features/core-check-update.feature @@ -76,6 +76,9 @@ Feature: Check for more recent versions And that HTTP requests to https://api.wordpress.org/core/version-check/1.7/ will respond with: """ HTTP/1.1 500 Internal Server Error + Content-Type: text/plain + + """ When I run `wp core check-update --force-check` From fed4c570eabc886136b0ee2ca18fc7632c2e8866 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:23:22 +0000 Subject: [PATCH 11/14] Use pre_http_request filter instead of http_api_debug to capture errors Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Core_Command.php | 48 ++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Core_Command.php b/src/Core_Command.php index 7f13160b..beecde3f 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -1472,14 +1472,15 @@ private function get_updates( $assoc_args ) { // Reset error tracking $this->version_check_error = null; - // Hook into HTTP API debug to capture errors during version check - add_action( 'http_api_debug', [ $this, 'capture_version_check_error' ], 10, 5 ); + // Hook into pre_http_request with max priority to capture errors during version check + // This is necessary because tests and plugins may use pre_http_request to mock responses + add_filter( 'pre_http_request', [ $this, 'capture_version_check_error' ], PHP_INT_MAX, 3 ); try { wp_version_check( [], $force_check ); } finally { // Ensure the hook is always removed, even if wp_version_check() throws an exception - remove_action( 'http_api_debug', [ $this, 'capture_version_check_error' ], 10 ); + remove_filter( 'pre_http_request', [ $this, 'capture_version_check_error' ], PHP_INT_MAX ); } /** @@ -1538,33 +1539,40 @@ private function get_updates( $assoc_args ) { } /** - * Handles the http_api_debug action to capture HTTP errors during version check. + * Handles the pre_http_request filter to capture HTTP errors during version check. * - * This method signature matches the http_api_debug action hook signature. - * Note: $class and $args parameters are not used but are required by the hook. + * This method signature matches the pre_http_request filter signature. + * Uses PHP_INT_MAX priority to run after test mocking and plugin modifications. * - * @param array|WP_Error $response HTTP response or WP_Error object. - * @param string $context Context of the HTTP request. - * @param string $_class HTTP transport class name (unused). - * @param array $_args HTTP request arguments (unused). - * @param string $url URL being requested. + * @param false|array|WP_Error $response A preemptive return value of an HTTP request. + * @param array $args HTTP request arguments. + * @param string $url The request URL. + * @return false|array|WP_Error The response, unmodified. */ - public function capture_version_check_error( $response, $context, $_class, $_args, $url ) { + public function capture_version_check_error( $response, $args, $url ) { if ( false === strpos( $url, 'api.wordpress.org/core/version-check' ) ) { - return; + return $response; } - // Only capture on response, not pre_response - if ( 'response' !== $context ) { - return; - } - - // Store the error if the response is a WP_Error; clear it otherwise. + // Store the error if the response is a WP_Error if ( is_wp_error( $response ) ) { $this->version_check_error = $response; - } else { + } elseif ( is_array( $response ) && isset( $response['response']['code'] ) && $response['response']['code'] >= 400 ) { + // HTTP error status code (4xx or 5xx) - convert to WP_Error for consistency + $this->version_check_error = new \WP_Error( + 'http_request_failed', + sprintf( + 'HTTP request failed with status %d: %s', + $response['response']['code'], + isset( $response['response']['message'] ) ? $response['response']['message'] : 'Unknown error' + ) + ); + } elseif ( false !== $response ) { + // Clear any previous error if we got a successful mocked response $this->version_check_error = null; } + + return $response; } /** From 0d24b1d5d4f0e8af5e2b8fa4ce617edab244534c Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sun, 25 Jan 2026 10:28:36 -0500 Subject: [PATCH 12/14] Fix test --- features/core-check-update.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/core-check-update.feature b/features/core-check-update.feature index 48bfe303..63877dbf 100644 --- a/features/core-check-update.feature +++ b/features/core-check-update.feature @@ -81,7 +81,7 @@ Feature: Check for more recent versions """ - When I run `wp core check-update --force-check` + When I try `wp core check-update --force-check` Then STDERR should contain: """ Warning: Failed to check for updates From 8ae12b6e0423b8071951b6b957e124b2737d2c92 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:31:57 +0000 Subject: [PATCH 13/14] Add http_api_debug hook alongside pre_http_request for comprehensive error capture Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Core_Command.php | 48 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/Core_Command.php b/src/Core_Command.php index beecde3f..9edf49ea 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -1476,11 +1476,16 @@ private function get_updates( $assoc_args ) { // This is necessary because tests and plugins may use pre_http_request to mock responses add_filter( 'pre_http_request', [ $this, 'capture_version_check_error' ], PHP_INT_MAX, 3 ); + // Also hook into http_api_debug to capture errors from real HTTP requests + // This fires when pre_http_request doesn't short-circuit the request + add_action( 'http_api_debug', [ $this, 'capture_version_check_error_from_response' ], 10, 5 ); + try { wp_version_check( [], $force_check ); } finally { - // Ensure the hook is always removed, even if wp_version_check() throws an exception + // Ensure the hooks are always removed, even if wp_version_check() throws an exception remove_filter( 'pre_http_request', [ $this, 'capture_version_check_error' ], PHP_INT_MAX ); + remove_action( 'http_api_debug', [ $this, 'capture_version_check_error_from_response' ], 10 ); } /** @@ -1575,6 +1580,47 @@ public function capture_version_check_error( $response, $args, $url ) { return $response; } + /** + * Handles the http_api_debug action to capture HTTP errors from real requests. + * + * This fires when pre_http_request doesn't short-circuit the request. + * Uses the http_api_debug action hook signature. + * + * @param array|WP_Error $response HTTP response or WP_Error object. + * @param string $context Context of the HTTP request. + * @param string $_class HTTP transport class name (unused). + * @param array $_args HTTP request arguments (unused). + * @param string $url URL being requested. + */ + public function capture_version_check_error_from_response( $response, $context, $_class, $_args, $url ) { + if ( false === strpos( $url, 'api.wordpress.org/core/version-check' ) ) { + return; + } + + // Only capture on response, not pre_response + if ( 'response' !== $context ) { + return; + } + + // Store the error if the response is a WP_Error + if ( is_wp_error( $response ) ) { + $this->version_check_error = $response; + } elseif ( is_array( $response ) && isset( $response['response']['code'] ) && $response['response']['code'] >= 400 ) { + // HTTP error status code (4xx or 5xx) - convert to WP_Error for consistency + $this->version_check_error = new \WP_Error( + 'http_request_failed', + sprintf( + 'HTTP request failed with status %d: %s', + $response['response']['code'], + isset( $response['response']['message'] ) ? $response['response']['message'] : 'Unknown error' + ) + ); + } else { + // Clear any previous error if we got a successful response + $this->version_check_error = null; + } + } + /** * Clean up extra files. * From 5d8c69399d1d8a581a082468c992e0d3efdb50db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 25 Jan 2026 15:50:50 +0000 Subject: [PATCH 14/14] Refactor: Extract common error handling logic into set_version_check_error helper method Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Core_Command.php | 63 +++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/Core_Command.php b/src/Core_Command.php index 9edf49ea..ae1c7397 100644 --- a/src/Core_Command.php +++ b/src/Core_Command.php @@ -1544,22 +1544,11 @@ private function get_updates( $assoc_args ) { } /** - * Handles the pre_http_request filter to capture HTTP errors during version check. - * - * This method signature matches the pre_http_request filter signature. - * Uses PHP_INT_MAX priority to run after test mocking and plugin modifications. + * Sets or clears the version check error property based on an HTTP response. * - * @param false|array|WP_Error $response A preemptive return value of an HTTP request. - * @param array $args HTTP request arguments. - * @param string $url The request URL. - * @return false|array|WP_Error The response, unmodified. + * @param mixed $response The HTTP response (WP_Error, array, or other). */ - public function capture_version_check_error( $response, $args, $url ) { - if ( false === strpos( $url, 'api.wordpress.org/core/version-check' ) ) { - return $response; - } - - // Store the error if the response is a WP_Error + private function set_version_check_error( $response ) { if ( is_wp_error( $response ) ) { $this->version_check_error = $response; } elseif ( is_array( $response ) && isset( $response['response']['code'] ) && $response['response']['code'] >= 400 ) { @@ -1572,10 +1561,34 @@ public function capture_version_check_error( $response, $args, $url ) { isset( $response['response']['message'] ) ? $response['response']['message'] : 'Unknown error' ) ); - } elseif ( false !== $response ) { - // Clear any previous error if we got a successful mocked response + } else { + // Clear any previous error if we got a successful response. $this->version_check_error = null; } + } + + /** + * Handles the pre_http_request filter to capture HTTP errors during version check. + * + * This method signature matches the pre_http_request filter signature. + * Uses PHP_INT_MAX priority to run after test mocking and plugin modifications. + * + * @param false|array|WP_Error $response A preemptive return value of an HTTP request. + * @param array $args HTTP request arguments. + * @param string $url The request URL. + * @return false|array|WP_Error The response, unmodified. + */ + public function capture_version_check_error( $response, $args, $url ) { + if ( false === strpos( $url, 'api.wordpress.org/core/version-check' ) ) { + return $response; + } + + // A `false` response means the request is not being preempted. + // In this case, we don't want to change the error status, as the subsequent + // `http_api_debug` hook will handle the actual response. + if ( false !== $response ) { + $this->set_version_check_error( $response ); + } return $response; } @@ -1602,23 +1615,7 @@ public function capture_version_check_error_from_response( $response, $context, return; } - // Store the error if the response is a WP_Error - if ( is_wp_error( $response ) ) { - $this->version_check_error = $response; - } elseif ( is_array( $response ) && isset( $response['response']['code'] ) && $response['response']['code'] >= 400 ) { - // HTTP error status code (4xx or 5xx) - convert to WP_Error for consistency - $this->version_check_error = new \WP_Error( - 'http_request_failed', - sprintf( - 'HTTP request failed with status %d: %s', - $response['response']['code'], - isset( $response['response']['message'] ) ? $response['response']['message'] : 'Unknown error' - ) - ); - } else { - // Clear any previous error if we got a successful response - $this->version_check_error = null; - } + $this->set_version_check_error( $response ); } /**