Make WordPress Core

Opened 5 months ago

Last modified 5 weeks ago

#64231 reviewing defect (bug)

Customizer fails to save when switching themes due to an orphaned setting left over from a previously active plugin

Reported by: alessandrolioce's profile alessandrolioce Owned by: westonruter's profile westonruter
Milestone: 7.1 Priority: normal
Severity: normal Version: 6.8.3
Component: Customize Keywords: has-patch has-test-info
Focuses: Cc:

Description

Description

When using the Customizer and switching themes with live preview, WordPress fails to save due to an unrecognized setting.
This happens when a plugin adds a custom setting to the Customizer, then gets deactivated before switching back to another theme.


Environment

  • WordPress v6.8.3
  • Active Theme: Twenty Twenty-One (v2.6)
  • Other used theme Twenty Twenty (v2.9)
  • Plugin: "Adds a testing option in customizer" (used to register “test_orphaned_setting”)


Steps to Reproduce

  1. Activate the plugin that adds a testing option in the Customizer.
  2. Go to Appearance > Customize.
  3. Edit the setting under Site Identity > Test Orphaned Setting.
  4. Without saving, switch to the Twenty Twenty theme using Live Preview, then click Activate & Publish.
  5. Deactivate the plugin (“Adds a testing option in customizer”).
  6. Go to Appearance > Customize again.
  7. Switch the theme back to Twenty Twenty-One using Live Preview.
  8. Click Activate & Publish.


Plugin that adds a testing option

<?php

/**
 * Plugin Name: Adds a testing option in customizer
 */

add_action( 'customize_register', function ( $wp_customize ) {
        $wp_customize->add_setting( 'test_orphaned_setting', array(
                'default'    => '',
                'type'       => 'theme_mod',
                'capability' => 'edit_theme_options',
                'transport'  => 'refresh',
        ) );

        $wp_customize->add_control( 'test_orphaned_setting', array(
                'label'   => 'Test Orphaned Setting',
                'section' => 'title_tagline',
                'type'    => 'text',
        ) );
} );


Observed Behavior

A POST request is sent to /wp-admin/admin-ajax.php with the following parameters:

wp_customize	“on”
customize_theme	“twentytwentyone”
nonce	“d3c3bbbe0e”
customize_changeset_uuid	“b92bc4d4-8665-49df-80ec-52ba9d8ec526”
customize_autosaved	“on”
customized	‘{“old_sidebars_widgets_data”:{“wp_inactive_widgets”:[“block-11”,“block-12”,“block-13”,“block-14”],“sidebar-1”:[“block-2”,“block-3”,“block-4”,“block-5”,“block-6”,“block-7”,“block-8”,“block-9”,“block-10”]},“nav_menu_locations[primary]”:3}’
customize_changeset_status	“publish”
action	“customize_save”
customize_preview_nonce	“bbf9d73816”

The JSON response returns:

{
  "success": false,
  "data": {
    "message": "Unable to save due to 1 invalid setting.",
    "code": "transaction_fail",
    "setting_validities": {
      "test_orphaned_setting": {
        "unrecognized": {
          "message": "Setting does not exist or is unrecognized.",
          "data": null
        }
      },
      "old_sidebars_widgets_data": true,
      "nav_menu_locations[primary]": true
    }
  }
}


Expected Behavior

Customizer should skip unrecognized (orphaned) settings left over from inactive plugins and allow the theme to be saved successfully.


Relevant Code

File: src/wp-includes/class-wp-customize-manager.php

Original Code

if ( isset( $stashed_theme_mods[ $stylesheet ] ) ) {
   $values = array_merge( $values, wp_list_pluck( $stashed_theme_mods[ $stylesheet ], 'value' ) );
}

Proposed fix

if ( isset( $stashed_theme_mods[ $stylesheet ] ) ) {
   $stashed_values = wp_list_pluck( $stashed_theme_mods[ $stylesheet ], 'value' );

   $valid_stashed_values = array_filter( $stashed_values, function ( $setting_id ) {
      return $this->get_setting( $setting_id );
   }, ARRAY_FILTER_USE_KEY );

   $values = array_merge( $values, $valid_stashed_values );
}

Additional Notes

This issue occurs because Customizer stashed theme mods may include references to settings that no longer exist after a plugin deactivation.
The fix ensures only recognized settings are restored, preventing “unrecognized setting” errors and allowing the theme activation to complete successfully.

Change History (8)

This ticket was mentioned in PR #10503 on WordPress/wordpress-develop by alessandrolioce.


5 months ago
#1

This PR prevents the Customizer from trying to save unrecognized (orphaned) settings left by deactivated plugins.
It validates stashed theme mods before merging them.

#2 @westonruter
5 months ago

  • Milestone changed from Awaiting Review to 7.0
  • Owner set to westonruter
  • Status changed from new to reviewing

#3 @palak678
5 months ago

Tested this on 6.8.3 and below are the results:-

After deactivating the plugin and switching themes back via Customizer, the save request fails.
The response returned 0, confirming the Customizer failed to handle the orphaned setting.

please refer below screenshot:-
https://prnt.sc/aVrVth_jGAuw

Also find below screenshot of return 0 response at /wp-admin/admin-ajax.php?action=customize_save

https://prnt.sc/fhMcPb8snM_x

This ticket was mentioned in Slack in #core-test by nikunj8866. View the logs.


4 months ago

#5 @r1k0
4 months ago

Test Report

Description

This report validates whether the indicated patch works as expected.

Patch tested: https://github.com/WordPress/wordpress-develop/pull/10503

Environment

  • WordPress: 6.9
  • PHP: 8.3.23
  • Server: Apache/2.4.43 (Unix)
  • Database: mysqli (Server: 8.0.35 / Client: mysqlnd 8.3.23)
  • Browser: Firefox 145.0
  • OS: Ubuntu
  • Theme: Twenty Twenty 3.0
  • MU Plugins: None activated
  • Plugins:
    • Adds a testing option in customizer
    • Test Reports 1.2.1

Actual Results

  1. ✅ Issue resolved with patch.
  2. Orphaned settings are ignored when switching to a different theme through live preview.
  3. Theme is activated successfully and no error appears in the customizer.
  4. The admin-ajax.php POST request returns:


{
  "success": true,
  "data": {
    "setting_validities": {
      "old_sidebars_widgets_data": true
    },
    "changeset_status": "publish",
    "next_changeset_uuid": "d93bc257-c0ae-4969-84bd-d22f540c0e43"
  }
}

Additional Notes

  • Used: Twenty Nineteen 3.2, to perform switch.

Supplemental Artifacts

Before:

https://i.ibb.co/b5cj1fXt/before-orphaned-setting.png

After:

https://i.ibb.co/ZzPJ5X76/after-orphaned-setting.png

https://i.ibb.co/6J8SbDMK/orphaned-setting-ignored.gif

Last edited 4 months ago by r1k0 (previous) (diff)

This ticket was mentioned in Slack in #core-test by ozgur_sar. View the logs.


7 weeks ago

@juanmaguitar commented on PR #10503:


7 weeks ago
#7

It appears there's a unit test failure caused by this:

All tests are passing now

#8 @westonruter
5 weeks ago

  • Milestone changed from 7.0 to 7.1

Sorry, I'm not going to have time to get this over the finish line for 7.0.

Note: See TracTickets for help on using tickets.