Opened 23 months ago
Last modified 6 months ago
#57469 reopened defect (bug)
retrieve_widgets(): fatal error when a sidebar's widgets set to null (array is expected)
Reported by: | kesselb | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 4.9 |
Component: | Widgets | Keywords: | has-patch has-unit-tests |
Focuses: | Cc: |
Description (last modified by )
When changing from PHP 7.4 to PHP 8.0 it's not possible to activate our theme.
Fatal error: Uncaught Error: array_merge(): Argument #3 must be of type array, null given in wp-includes/widgets.php on line 1342
array_merge() wp-includes/widgets.php:1342 retrieve_widgets() wp-includes/widgets.php:1287 _wp_sidebars_changed() wp-includes/class-wp-hook.php:310 WP_Hook::apply_filters() wp-includes/class-wp-hook.php:332 WP_Hook::do_action() wp-includes/plugin.php:517 do_action() wp-includes/theme.php:3395 check_theme_switched() wp-includes/class-wp-hook.php:308 WP_Hook::apply_filters() wp-includes/class-wp-hook.php:332 WP_Hook::do_action() wp-includes/plugin.php:517 do_action() wp-settings.php:617 require_once() wp-config.php:103 require_once() wp-load.php:50 require_once() wp-admin/admin.php:34 require_once() wp-admin/plugins.php:10
Line 1342:
<?php $shown_widgets = array_merge( ...array_values( $sidebars_widgets ) );
$sidebars_widgets
array ( 'wp_inactive_widgets' => array ( ), 'sidebar-standard' => array ( ), 'sidebar-marken' => NULL, 'sidebar-typen' => NULL, 'sidebar-test' => NULL, 'sidebar-zubehoer' => NULL, 'sidebar-ratgeber' => NULL, )
PHP 8.0+ throws a type error when a non-array value is given to array_merge.
I guess NULL is not a valid value for the sidebar widgets.
Maybe our theme wrote this weird state to the options field.
Patch: https://github.com/WordPress/wordpress-develop/pull/3848
Attachments (2)
Change History (15)
This ticket was mentioned in PR #3848 on WordPress/wordpress-develop by kesselb.
23 months ago
#1
- Keywords has-patch has-unit-tests added
#2
@
23 months ago
- Keywords php8 added
- Milestone changed from Awaiting Review to 6.2
- Version 6.1.1 deleted
Thanks for the ticket, the patch and the unit tests!
I left a comment in the PR.
Moving for 6.2 consideration.
#3
follow-up:
↓ 6
@
23 months ago
- Keywords close added
- Milestone 6.2 deleted
@kesselb Thanks for the ticket.
To be honest, this sounds like user error and something which should be fixed in the theme, not in WP Core.
If anything, a _doing_it_wrong
should be thrown when receiving invalid data (as is the case with your use-case).
#4
@
23 months ago
Hi,
If anything, a _doing_it_wrong should be thrown when receiving invalid data (as is the case with your use-case).
Sounds good ;)
<?php function check_sidebars_widgets_for_invalid_values($value) { if (is_array($value)) { $value = array_filter($value, static function ($var) { return $var !== null; }); } return $value; } /** * Upgrade to PHP 8 fails on some pages with an uncaught error: * * array_merge(): Argument #3 must be of type array, null given in wp-includes/widgets.php on line 1342 * * Starting with PHP 8 array_merge is stricter about null values. * This filter will remove sidebars with null as value. */ add_filter('option_sidebars_widgets', 'check_sidebars_widgets_for_invalid_values', 1, 1);
If anyone has a similar issue. The above filter prevent the fatal error.
#5
@
16 months ago
- Description modified (diff)
- Keywords php80 added; php8 has-patch has-unit-tests removed
- Summary changed from Uncaught Error: array_merge(): Argument #3 must be of type array, null given in wp-includes/widgets.php on line 1342 to retrieve_widgets(): fatal error when a sidebar's widgets set to null (array is expected)
- Version set to 4.9
Changes in the ticket:
- Updated the Summary to better reflect the issue being reported, i.e. for discoverability.
- Updated the Version to 4.9.
- Wrapped the PHP error in the Description.
- Reset the keywords as the PR was closed.
- Changed keyword to
php80
to identify which PHP version increased the error's severity.
Error across PHP versions:
If null
or a non-array is set for the widgets of a sidebar, then PHP throws an error (see it in action https://3v4l.org/i45nZ):
- < 7.3:
Warning: array_merge(): Argument #3 is not an array
- PHP 7.3 to 7.4:
Warning: array_merge(): Expected parameter 3 to be an array, null given
- PHP 8+:
Fatal error: Uncaught TypeError: array_merge(): Argument #3 must be of type array, null given
.
Historical context:
- [41555] / #39693 (during WP 4.9):
- Introduced
wp_map_sidebars_widgets()
. retrieve_widgets()
:- Invoked
wp_map_sidebars_widgets()
to map$sidebars_widgets
- Added
$shown_widgets = call_user_func_array( 'array_merge', $sidebars_widgets );
.
- Invoked
- Introduced
- [48839] / #50913 (during WP 5.6):
retrieve_widgets()
: changedcall_user_func_array( 'array_merge', $sidebars_widgets );
toarray_merge( ...array_values( $sidebars_widgets ) );
.
#6
in reply to:
↑ 3
@
16 months ago
- Resolution set to invalid
- Status changed from new to closed
Replying to jrf:
To be honest, this sounds like user error and something which should be fixed in the theme, not in WP Core.
I agree. The error flagging null
as the wrong data type and informing it should an array
has been present for a long time. This is a case of doing it wrong.
I'm all for defensive code to protect Core's source code. However, sometimes a native PHP error is appropriate.
When changing from PHP 7.4 to PHP 8.0 it's not possible to activate our theme.
I think in this case, not being able to activate a theme is not severe enough to warrant adding defensive guard and _doing_it_wrong()
.
A user using the theme with the issue upgrading to PHP 8+ would experience a fatal error, which would require manual action to restore the site. Changing Core's code for this scenario is dependent upon the frequency of this scenario happening. But I'm not seeing other reports to null
for widgets causing a fatal error.
Thus, I tend to agree with @jrf to close this ticket as something to be fixed in the theme.
#8
@
16 months ago
#58351 reported the same issue but happened after switching themes:
In some subsites, that after switched themes I get the following PHP Fatal error.
@lenasterg As noted in this ticket, the root cause seems to be a problem in the theme. Can you confirm if switching back to the original theme or to a different theme resolved the issue?
#9
@
10 months ago
Hey there, just came across this issue on a recent WordPress 6.4.2 installation switching a working site with the "Enfold" Theme to "Twenty Twenty-Four" Theme.
Uncaught exception (TypeError): “array_merge(): Argument #3 must be of type array, null given“ at `./wp-includes/widgets.php:1346`.
If this is a "User Error" I am not aware of any obvious one. The site was working perfectly fine before.
We switched back to Enfold using WP-CLI but the site remains broken with the same error.
#10
@
10 months ago
Deleting the "theme_mods_twentytwentyfour" option from the DB made the site useable again.
This was the content of that option:
a:3:{i:0;b:0;s:18:"nav_menu_locations";a:0:{}s:19:"wp_classic_sidebars";a:6:{s:13:"av_everywhere";a:11:{s:4:"name";s:20:"Displayed Everywhere";s:2:"id";s:13:"av_everywhere";s:11:"description";s:0:"";s:5:"class";s:0:"";s:13:"before_widget";s:48:"<section id="%1$s" class="widget clearfix %2$s">";s:12:"after_widget";s:59:"<span class="seperator extralight-border"></span></section>";s:12:"before_title";s:24:"<h3 class="widgettitle">";s:11:"after_title";s:5:"</h3>";s:14:"before_sidebar";s:0:"";s:13:"after_sidebar";s:0:"";s:12:"show_in_rest";b:0;}s:7:"av_blog";a:11:{s:4:"name";s:12:"Sidebar Blog";s:2:"id";s:7:"av_blog";s:11:"description";s:0:"";s:5:"class";s:0:"";s:13:"before_widget";s:48:"<section id="%1$s" class="widget clearfix %2$s">";s:12:"after_widget";s:59:"<span class="seperator extralight-border"></span></section>";s:12:"before_title";s:24:"<h3 class="widgettitle">";s:11:"after_title";s:5:"</h3>";s:14:"before_sidebar";s:0:"";s:13:"after_sidebar";s:0:"";s:12:"show_in_rest";b:0;}s:8:"av_pages";a:11:{s:4:"name";s:13:"Sidebar Pages";s:2:"id";s:8:"av_pages";s:11:"description";s:0:"";s:5:"class";s:0:"";s:13:"before_widget";s:48:"<section id="%1$s" class="widget clearfix %2$s">";s:12:"after_widget";s:59:"<span class="seperator extralight-border"></span></section>";s:12:"before_title";s:24:"<h3 class="widgettitle">";s:11:"after_title";s:5:"</h3>";s:14:"before_sidebar";s:0:"";s:13:"after_sidebar";s:0:"";s:12:"show_in_rest";b:0;}s:11:"av_footer_1";a:11:{s:4:"name";s:17:"Footer - Column 1";s:2:"id";s:11:"av_footer_1";s:11:"description";s:0:"";s:5:"class";s:0:"";s:13:"before_widget";s:48:"<section id="%1$s" class="widget clearfix %2$s">";s:12:"after_widget";s:59:"<span class="seperator extralight-border"></span></section>";s:12:"before_title";s:24:"<h3 class="widgettitle">";s:11:"after_title";s:5:"</h3>";s:14:"before_sidebar";s:0:"";s:13:"after_sidebar";s:0:"";s:12:"show_in_rest";b:0;}s:11:"av_footer_2";a:11:{s:4:"name";s:17:"Footer - Column 2";s:2:"id";s:11:"av_footer_2";s:11:"description";s:0:"";s:5:"class";s:0:"";s:13:"before_widget";s:48:"<section id="%1$s" class="widget clearfix %2$s">";s:12:"after_widget";s:59:"<span class="seperator extralight-border"></span></section>";s:12:"before_title";s:24:"<h3 class="widgettitle">";s:11:"after_title";s:5:"</h3>";s:14:"before_sidebar";s:0:"";s:13:"after_sidebar";s:0:"";s:12:"show_in_rest";b:0;}s:11:"av_footer_3";a:11:{s:4:"name";s:17:"Footer - Column 3";s:2:"id";s:11:"av_footer_3";s:11:"description";s:0:"";s:5:"class";s:0:"";s:13:"before_widget";s:48:"<section id="%1$s" class="widget clearfix %2$s">";s:12:"after_widget";s:59:"<span class="seperator extralight-border"></span></section>";s:12:"before_title";s:24:"<h3 class="widgettitle">";s:11:"after_title";s:5:"</h3>";s:14:"before_sidebar";s:0:"";s:13:"after_sidebar";s:0:"";s:12:"show_in_rest";b:0;}}}
#11
@
10 months ago
- Resolution invalid deleted
- Status changed from closed to reopened
I was sitting on an old theme for a few years, and I hit this bug. I would see a TypeError exception in array_merge() any time I open the 'widgets' page, or after I have upgraded to a new theme.
This seems to be caused by corrupted widgets information in the database. An investigation showed that $sidebars_widgets array contains a NULL item with key 'subsidiary'.
I.e. it looked like this:
( [wp_inactive_widgets] => Array(...) [primary] => Array(...) [subsidiary] => NULL )
Since $sitebars_widgets is a global variable, it is hard to tell who and why was adding a NULL element. Anyway, the problem goes away if I add the following to retrieve_widgets() in wp-incudes/widgets.php just before the call to _wp_remove_unregistered_widgets():
// remove any NULL elements $sidebars_widgets = array_filter($sidebars_widgets);
I suggest to reopen this bug and add this filter to the production version: corrupted databases happen, and it's an easy precaution.
#12
@
9 months ago
Just a quick confirmation: I had this problem too and couldn't find the source. The line of code @ikriv suggests above worked to solve it for me.
#13
@
6 months ago
- Keywords has-patch has-unit-tests added; php80 close removed
@hellofromTonya just wanted to re-ping you about this issue. It seems obvious that this is not related to a specific Theme doing something wrong as detailed within this ticket. The broken data might just be inserted by any Theme or Plugin without the knowledge of the user.
Then when switching from <any> Theme to twenty24 for example the site is broken. Causing frustration as the "old" theme obviously worked before.
There are two fixes. One as a patch and the other one in: https://core.trac.wordpress.org/ticket/57469#comment:11
We tested the second one and as simple as it is, it simply works ;-)
Should be a safe ticket for 6.6 as it has no real negative impact at all. Shouldn't it?
What do you mean?
Thank you!
wp_map_sidebar_widgets is called in retrieve_widgets and is expected to return array<string, array>.
Before this change it was possible to return something like
['sidebar-1' => [], 'sidebar-2' => null]
.PHP 7.4:
array_merge(...[['hello', 'world'], null])
=> nullPHP 8.0:
array_merge(...[['hello', 'world'], null])
=> Fatal errorTrac ticket: https://core.trac.wordpress.org/ticket/57469