Problem/Motivation

Sporadically we get the following warning:
Warning: uasort(): Array was modified by the user comparison function in Drupal\Core\Plugin\DefaultLazyPluginCollection->sort() (line 100 of core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php).

A 100% repo is to use the "Entity Browser Module" when using a file field (in our case inside a field collection) with the File Browser widget.

Proposed resolution

According to this link:
http://shout.setfive.com/2013/06/14/symfony2-usort-array-was-modified-by...

The problem lies in the lazy loading of the plugin collection. So the fix is simple. In the sort() function (DefaultLazyLoadingPluginCollection) iterate through the array like this:

  public function sort() {
    // iterate to populatae the array
    foreach($this->instanceIDs as $id){
      $pluginId = $this->get($id)->getPluginId();
    }
    // original code
    uasort($this->instanceIDs, array($this, 'sortHelper'));
    return $this;
  }

Remaining tasks

reviews needed, tests to be written and run

User interface changes

none

API changes

none

Data model changes

none

Original report by [username]

none

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Denis Danielyan created an issue. See original summary.

joachim’s picture

Status: Needs review » Needs work
Issue tags: -PHP warnings (duplicate tag)

Seeing this too. For me it happened when I enabled Web Profiler.

Changing to Needs Work, as there's no patch here to review.

niccottrell’s picture

Version: 8.0.5 » 8.1.2

I'm getting something similar via a new view:

uasort(): Array was modified by the user comparison function', '..../core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php', 90, Array)
uasort(Array, Array) (Line: 90)
Drupal\Core\Plugin\DefaultLazyPluginCollection->sort() (Line: 84)
Drupal\filter\FilterPluginCollection->sort() (Line: 137)
Drupal\filter\Entity\FilterFormat->filters() (Line: 99)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func(Array, Array) (Line: 381)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 932)
render(Array) (Line: 889)
Drupal\views\Plugin\views\field\Field->render_item(0, Array) (Line: 1146)
Drupal\views\Plugin\views\field\FieldPluginBase->advancedRender(Object) (Line: 224)
template_preprocess_views_view_field(Array, 'views_view_field', Array) (Line: 287)
Drupal\Core\Theme\ThemeManager->render(Array, Array) (Line: 435)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 1703)
Drupal\views\Plugin\views\field\FieldPluginBase->theme(Object) (Line: 765)
Drupal\views\Plugin\views\style\StylePluginBase->elementPreRenderRow(Array)
call_user_func(Array, Array) (Line: 381)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 713)
Drupal\views\Plugin\views\style\StylePluginBase->renderFields(Array) (Line: 580)
Drupal\views\Plugin\views\style\StylePluginBase->renderGrouping(Array, Array, 1) (Line: 467)
Drupal\views\Plugin\views\style\StylePluginBase->render(Array) (Line: 2116)
Drupal\views\Plugin\views\display\DisplayPluginBase->render() (Line: 1518)
Drupal\views\ViewExecutable->render() (Line: 170)
Drupal\views\Plugin\views\display\Page->execute() (Line: 1615)
Drupal\views\ViewExecutable->executeDisplay('page_2', Array) (Line: 78)
Drupal\views\Element\View::preRenderViewElement(Array)
call_user_func(Array, Array) (Line: 381)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 226)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 574)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 227)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 117)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object) (Line: 144)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 62)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 98)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 77)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 628)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
chishah92’s picture

Assigned: Unassigned » chishah92
chishah92’s picture

Assigned: chishah92 » Unassigned
lhuria94’s picture

Assigned: Unassigned » lhuria94
lhuria94’s picture

Iterating the IDs through the array. Attaching patch. Please review.

lhuria94’s picture

Status: Needs work » Needs review
lhuria94’s picture

Assigned: lhuria94 » Unassigned
Xano’s picture

Version: 8.1.2 » 8.1.x-dev
Status: Needs review » Needs work

Sporadically we get the following warning

Can you provide a test case to reproduce this problem, or step-by-step instructions so we can reproduce the problem manually? We would also need to know which versions of PHP cause problems and which ones don't.

RobLoach’s picture

In this patch, $this->get($id)->getPluginId() is iterated across, but it doesn't actually do anything with `$pluginId`. What does this actually accomplish?

Denis Danielyan’s picture

it doesn't actually do anything with `$pluginId`. What does this actually accomplish?

The warning is thrown because the array is modifed while usort() is run.

According to the supplied link the problem is:

because of how Doctrine’s lazy loading functionality works if the usort callback function causes Doctrine to lazy load it’ll silently modify the array and cause that warning

So to fix that

you just need to force the lazy loading before sorting the collection

This is done by iterating over $this->instanceIDs.
Calling $this->get($id)->getPluginId(); might actually not be needed as lazy loading is triggered by the iterator.
Also assigning the result of getPluginId() to a variable is not necessary.

Why is it there then? I don't really remember if the for each loop was optimized away at runtime without the assignment line or if I thought it might happen.

a.milkovsky’s picture

Having this issue as well.

I can see the error when I try to add a Media entity(drupal/media_entity_image) to a node.

I can see the same uasort warning but in different classes in other places as well. Modules page /admin/modules and node save with tokens: #2671060: Use SortArray::stableUasort instead uasort to prevent warnings (Array was modified by the user comparison function)

PHP Version: PHP 5.5.9-1ubuntu4.14 (cli) (built: Oct 28 2015 01:34:46)
Drush version: 8.0.2.

#7 hides the warning in this place for me.

This issue is related to the PHP Bug #50688 Using exceptions inside usort() callback function causes a warning.

If you do not have this error, could you please write which PHP version do you use?

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Tomefa’s picture

Is this patch gonna be include in core on day ?

It correct the functionnality with the media module.

Tomefa’s picture

Status: Needs work » Needs review
geerlingguy’s picture

I've noticed this warning when installing the Lightning module as part of a vanilla BLT configuration, either via a CI tool or locally using blt local:setup

tenken’s picture

@geerlingguy, unless I'm mistaken Lightning is a D8 profile and not a module.

I too just tried installing Lightning via composer and saw the same Warning

Other D8 modules using uasort() report a similar issue also mention this is a known php uasort bug():
https://www.drupal.org/node/2670942 [token module]

php issue:
https://bugs.php.net/bug.php?id=50688 [known php5 issue, fixed in php 7]

I'm not sure what the proper resolution is given it's resolved in some versions of php.

geerlingguy’s picture

@tenken - Ah, didn't realize it's been fixed in PHP 7. Hopefully we'll be able to move this particular site I'm working on to PHP 7 soon... then this will be a non-issue :)

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

phenom’s picture

Version: 8.3.x-dev » 8.2.7

Hello

for a quick fix, add @ before uasort

@uasort($this->instanceIDs, array($this, 'sortHelper'));

related https://www.drupal.org/node/2628884

joachim’s picture

Version: 8.2.7 » 8.3.x-dev

Restoring the version number.

mpotter’s picture

Here is an update to this patch.

* Removed the un-needed variable assignment
* Improved the comment
* Re-rolled for 8.3.x

shaisamuel’s picture

#23 Works for me to fix this error, when image was loading:
uasort(): Array was modified by the user comparison function in /home/devbwfu/public_html/core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php on line 90

iSoLate’s picture

Patch #23 fixed it for me.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jhedstrom’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

This fix looks good. It will need test coverage though.

apaderno’s picture

Version: 8.6.x-dev » 8.9.x-dev

I guess it needs a re-roll again.

Hardik_Patel_12’s picture

Patch #23 re-rolled for 8.9.x-dev.

apaderno’s picture

It still needs test coverage, which the patch in the previous comment doesn't include.

jungle’s picture

One question, should change $instanceIDs to $instanceIds? could not find where it is documented, I remember, for abbreviation in class methods and properties, it should uppercase the first letter only.

apaderno’s picture

Yes, it should be LazyPluginCollection::$instanceIds (see Object-oriented code, Naming conventions), but that can be fixed in a different issue.

jungle’s picture

Thanks, @kiamlaluno! A child issue added.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

mpotter’s picture

mpotter’s picture

Ran into a new problem with this patch on D8.9.0. When creating a simple Functional test that inherits from `BrowserTestBase` if you tell it to install the `node` module, then even with an empty test I get the error:

1) Drupal\Tests\octane_ci_test\Functional\OctaneCiTest::testCi
Undefined property: Drupal\filter\FilterPluginCollection::$instanceIDs

/var/www/build/docroot/core/lib/Drupal/Core/Plugin/DefaultLazyPluginCollection.php:92
/var/www/build/docroot/core/modules/filter/src/FilterPluginCollection.php:84
/var/www/build/docroot/core/modules/filter/src/Entity/FilterFormat.php:144
/var/www/build/docroot/core/modules/filter/src/Entity/FilterFormat.php:205
/var/www/build/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php:499
/var/www/build/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php:454
/var/www/build/docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php:263
/var/www/build/docroot/core/lib/Drupal/Core/Entity/EntityBase.php:395
/var/www/build/docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php:616
/var/www/build/docroot/core/lib/Drupal/Core/Config/ConfigInstaller.php:371
/var/www/build/docroot/core/lib/Drupal/Core/Config/ConfigInstaller.php:137
/var/www/build/docroot/core/lib/Drupal/Core/ProxyClass/Config/ConfigInstaller.php:75
/var/www/build/docroot/core/lib/Drupal/Core/Extension/ModuleInstaller.php:288
/var/www/build/docroot/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php:83
/var/www/build/docroot/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php:476
/var/www/build/docroot/core/tests/Drupal/Tests/BrowserTestBase.php:578
/var/www/build/docroot/core/tests/Drupal/Tests/BrowserTestBase.php:406

Notice this error happens on line 92, which is the new line added by this patch:

    foreach ($this->instanceIDs as $id) {
      $this->get($id)->getPluginId();
    }

Not sure what could cause this since every instance of DefaultLazyPluginCollection should have an instanceIDs property. I'd have to look at what changed in core to understand this more. So just beware when using this patch in 8.9.x

epicflux’s picture

@mpotter it looks like there was a change in the variable name to $this->instanceIds. I updated your patch with that change.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mashot7’s picture

Is there a patch for 9.3.7?

#39 is not applying.

yogeshmpawar’s picture

Resolved CSpell errors & added interdiff.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

quietone’s picture

Status: Needs review » Closed (outdated)
Issue tags: +Bug Smash Initiative

A related issue was a bugsmash target this week. Both lendude and I discussed it.

We concluded that this can be closed as outdated. The full details are in #2831964-19: Warning: uasort(): Array was modified by the user comparison function in Drupal\Core\Config\Entity\ConfigEntityListBuilder->load().