Commit dfa7dca5c38 for woocommerce
commit dfa7dca5c38639df58d2f5f20e8007d836a0259a
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date: Wed May 27 18:25:08 2026 +0300
Fix DefaultCustomerAddress autoload race during 10.7→10.8 in-place upgrade (#65337)
* fix(settings): pre-load DefaultCustomerAddress enum to dodge upgrade-time autoload race
Context: WC 10.8.0 added the Automattic\WooCommerce\Enums\DefaultCustomerAddress
enum and referenced its constants from class-wc-settings-general.php for the
"Default customer location" setting.
Problem: PR #64091 (10.8.0) landed the enum reference in a file reachable from
the AssetDataRegistry chain that update.php's iframe footer triggers via
admin_print_footer_scripts. On a same-request in-place upgrade from 10.7.x,
the Jetpack autoloader's in-memory Version_Loader::$classmap is the snapshot
captured at request start (pre-upgrade) and therefore does not contain the new
enum class. When the post-swap class-wc-settings-general.php loads fresh from
disk and evaluates DefaultCustomerAddress::BASE, PHP autoloads via the stale
classmap, gets a miss (no PSR-4 fallback for the WC namespace in the shipped
jetpack_autoload_psr4.php — that file isn't generated), and fatals with
"Class Automattic\WooCommerce\Enums\DefaultCustomerAddress not found" at
line 237 of class-wc-settings-general.php. Site stays up, db migrates to
10.8.0-2, next request works — but admins get a fatal-error email from WP.
Solution: bypass the autoloader for this one class by require_once'ing its
file at the top of class-wc-settings-general.php. The class is final and
dependency-free, so the include is idempotent and safe. The enum is still
the canonical definition; the eight other includes/ files that reference it
keep using the enum constants because they are loaded during WC's normal
boot (their class definitions get pinned to the pre-upgrade version in PHP's
class table, so the post-swap file content never executes).
This is a narrow hotfix for the specific reported file. The underlying race
applies structurally to any new class added in version N+1 that's referenced
from files reachable during the update.php iframe footer; that bug class is
tracked in #54657 and is best fixed by hooking AssetDataRegistry's enqueue
earlier so the settings page loads BEFORE the file swap completes (a draft
PR #65005 explored this approach).
Refs #54657
* fix(settings): guard DefaultCustomerAddress preload with class_exists()
Wraps the require_once added in the prior commit with a class_exists(..., false)
guard. Matches the defensive pattern in class-wc-gateway-paypal.php (PR #62789)
and keeps this safe under opcache.preload or any other mechanism that may have
already defined the class before the file is included. The require_once on its
own is already idempotent via PHP's realpath tracking — confirmed empirically
on the docker stack for both 10.7→fix-build and 10.8.0→fix-build in-place
upgrades — but the guard makes the intent explicit and stays consistent with
the rest of the codebase.
No functional change for the realistic in-place upgrade paths.
Refs #65337
diff --git a/plugins/woocommerce/changelog/fix-defaultcustomeraddress-autoload-race b/plugins/woocommerce/changelog/fix-defaultcustomeraddress-autoload-race
new file mode 100644
index 00000000000..507b980eff8
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-defaultcustomeraddress-autoload-race
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix a fatal error during in-place upgrade to 10.8.0 caused by the new DefaultCustomerAddress enum being referenced from class-wc-settings-general.php before the in-process autoloader classmap is refreshed.
diff --git a/plugins/woocommerce/includes/admin/settings/class-wc-settings-general.php b/plugins/woocommerce/includes/admin/settings/class-wc-settings-general.php
index 674d4990af4..a903d0b2d61 100644
--- a/plugins/woocommerce/includes/admin/settings/class-wc-settings-general.php
+++ b/plugins/woocommerce/includes/admin/settings/class-wc-settings-general.php
@@ -11,6 +11,25 @@ use Automattic\WooCommerce\Internal\AddressProvider\AddressProviderController;
defined( 'ABSPATH' ) || exit;
+/*
+ * Pre-load the enum file because the in-process Jetpack autoloader classmap is
+ * captured at request start by the pre-upgrade plugin version, so during a same-
+ * request in-place upgrade it will not contain new src/Enums/* classes added in
+ * the new version. Without this, the DefaultCustomerAddress::* references below
+ * would trigger an autoloader miss and a "Class not found" fatal during the
+ * upgrade-completion iframe of /wp-admin/update.php.
+ *
+ * The class_exists() guard (with autoload disabled) matches the defensive
+ * pattern used elsewhere in includes/, e.g. class-wc-gateway-paypal.php, and
+ * keeps this safe under opcache.preload or any other mechanism that may have
+ * already defined the class before the file is included.
+ *
+ * The architectural fix lives in https://github.com/woocommerce/woocommerce/issues/54657.
+ */
+if ( ! class_exists( '\Automattic\WooCommerce\Enums\DefaultCustomerAddress', false ) ) {
+ require_once dirname( WC_PLUGIN_FILE ) . '/src/Enums/DefaultCustomerAddress.php';
+}
+
if ( class_exists( 'WC_Settings_General', false ) ) {
return new WC_Settings_General();
}