Skip to content
Closed
Changes from 3 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
80b2114
Initial plan
Copilot Nov 7, 2025
0434a0f
Add error handling for require_once statements in core install methods
Copilot Nov 7, 2025
27758fe
Refactor error handling with require_upgrade_file helper method
Copilot Nov 7, 2025
a1b8628
Update src/Core_Command.php
swissspidy Nov 8, 2025
3e9d6c1
Update src/Core_Command.php
swissspidy Nov 8, 2025
16b95f2
Prevent shutdown handler from executing after successful require_once
Copilot Nov 8, 2025
e94788f
Simplify error handling - WP_CLI::error() is always available
Copilot Nov 8, 2025
f946f18
PHPStan fix
swissspidy Nov 10, 2025
015f95e
Merge branch 'main' into copilot/fix-core-install-error-255
swissspidy Dec 19, 2025
138666f
Merge branch 'main' into copilot/fix-core-install-error-255
swissspidy Jan 20, 2026
44b1daa
Remove E_COMPILE_WARNING from error types - it's non-fatal
Copilot Jan 20, 2026
62c21f6
Add Behat tests for error handling in core install
Copilot Feb 15, 2026
afcc087
Update test to simulate missing mysqli extension scenario
Copilot Feb 15, 2026
75bcd25
Merge branch 'main' into copilot/fix-core-install-error-255
swissspidy Feb 15, 2026
0314e92
Fix test to avoid PHP parse error when simulating missing extension
Copilot Feb 15, 2026
6fc1337
Improve error message to clarify WordPress core vs plugin/theme errors
Copilot Mar 11, 2026
bb95bbc
Merge branch 'main' into copilot/fix-core-install-error-255
swissspidy Mar 11, 2026
6079593
Apply suggestion from @swissspidy
swissspidy Mar 11, 2026
a00b72d
Lint fix
swissspidy Mar 11, 2026
de24fc3
Simplify error handling to work with WP-CLI's built-in shutdown handler
Copilot Mar 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions src/Core_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@
add_filter( 'send_site_admin_email_change_email', '__return_false' );
}

require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$this->require_upgrade_file( 'WordPress installation' );

$defaults = [
'title' => '',
Expand Down Expand Up @@ -715,7 +715,7 @@
private function multisite_convert_( $assoc_args ) {
global $wpdb;

require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$this->require_upgrade_file( 'multisite conversion' );

$domain = self::get_clean_basedomain();
if ( 'localhost' === $domain && ! empty( $assoc_args['subdomains'] ) ) {
Expand Down Expand Up @@ -1211,7 +1211,7 @@
&& ( $update->version !== $wp_version
|| Utils\get_flag_value( $assoc_args, 'force' ) ) ) {

require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$this->require_upgrade_file( 'WordPress core update' );

if ( $update->version ) {
WP_CLI::log( "Updating to version {$update->version} ({$update->locale})..." );
Expand Down Expand Up @@ -1371,7 +1371,7 @@
}
WP_CLI::success( "WordPress database upgraded on {$success}/{$total} sites." );
} else {
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$this->require_upgrade_file( 'WordPress database update' );

/**
* @var string $wp_current_db_version
Expand Down Expand Up @@ -1663,4 +1663,49 @@
WP_CLI::error( 'ZipArchive failed to open ZIP file.' );
}
}

/**
* Safely requires the WordPress upgrade.php file with error handling.
*
* This method checks for file existence and readability before requiring,
* and registers a shutdown function to catch fatal errors during file loading
* (e.g., missing PHP extensions or other runtime issues).
*
* @param string $context Context for error messages (e.g., 'installation', 'upgrade', 'database update').
*/
private function require_upgrade_file( $context = 'WordPress operation' ) {
$upgrade_file = ABSPATH . 'wp-admin/includes/upgrade.php';

if ( ! file_exists( $upgrade_file ) ) {
WP_CLI::error( "WordPress installation is incomplete. The file '{$upgrade_file}' is missing." );
}

if ( ! is_readable( $upgrade_file ) ) {
WP_CLI::error( "Cannot read WordPress installation file '{$upgrade_file}'. Check file permissions." );
}

// Register a shutdown function to catch fatal errors during require_once.
$shutdown_handler = function () use ( $upgrade_file, $context ) {

Check failure on line 1688 in src/Core_Command.php

View workflow job for this annotation

GitHub Actions / code-quality / PHPStan

Anonymous function has an unused use $upgrade_file.
Comment thread
swissspidy marked this conversation as resolved.
Outdated
$error = error_get_last();
if ( null !== $error && in_array( $error['type'], [ E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR ], true ) ) {
// Check if error occurred in the upgrade file or files it includes.
if ( false !== strpos( $error['file'], 'wp-admin/includes/' ) || false !== strpos( $error['file'], 'wp-includes/' ) ) {
Comment thread
swissspidy marked this conversation as resolved.
Outdated
WP_CLI::error(
sprintf(
"Failed to load WordPress files for %s. This often indicates a missing PHP extension or a corrupted WordPress installation.\n\nError: %s in %s on line %d\n\nPlease check that all required PHP extensions are installed and that your WordPress installation is complete.",
$context,
$error['message'],
$error['file'],
$error['line']
)
);
Comment thread
swissspidy marked this conversation as resolved.
Outdated
}
}
};
Comment thread
swissspidy marked this conversation as resolved.
Outdated

register_shutdown_function( $shutdown_handler );

// phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- Path comes from WordPress itself.
require_once $upgrade_file;
}
}
Loading