Problem/Motivation
When triggering two AJAX requests subsequently on a node edit / add page and making sure you trigger the last one before the first one can finish, the Media Library modal will open up. This only seem to happen if there is another Media field in the page. I reproduce this with the Paragraphs module, though I'm not certain if that module has a specific role in this bug, I'm having the feeling it will trigger in any AJAX action.
This bug get's real tedious in some specific production environments, where we've encountered node setups where there are file fields that need to be filled and people will add them too quickly also triggering this bug. At this specific event, they weren't even able to click any more buttons, forcing them to hard reload the page and lose their progress.
Steps to reproduce
- Install Drupal (I used 8.9.2 in this reproduction case) with the standard installation profile
- Install Media and Media Library modules
- Download and install the Paragraphs module
- Setup a Media field in the Page node, default settings
- Setup a simple paragraph type with for example a text field
- Setup a paragraph reference field in the Page node
- Go to the node add page for Page
- Add two additional paragraphs for a total of minimal 3
- Try to delete the two added paragraphs, making sure you click the "Remove" button before the throttler of the first one is finished
- Note that the "Add or select media" dialog opens
Also see the screen recording I added for a more visual explanation.
Proposed resolution
Fix it
Remaining tasks
N/A
User interface changes
N/A
API changes
N/A
Data model changes
N/A
Release notes snippet
N/A
| Comment | File | Size | Author |
|---|---|---|---|
| #16 | kernel-request-vs-query.JPG | 283.53 KB | anybody |
| #14 | request backtrace.JPG | 254.72 KB | anybody |
| #14 | form-debug-backtrace.JPG | 406.11 KB | anybody |
| #11 | media entity trigger.JPG | 78.56 KB | anybody |
| #11 | media browser modal bug.png | 88.48 KB | anybody |
Issue fork drupal-3174361
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
nvakenComment #3
paulocsHello, which paragraph version are you using?
My paragraph is different from yours. I downloaded the last dev version. See my scream shot.
Or is there anyway to configure and set the "Remove" button instead of the "Collapse" button?
Comment #4
nvakenHi paulocs! I'm using Paragraphs 8.x-1.12, I can imagine that this is a difference in field form settings? Attached are my settings.
Comment #5
larowlanCan you confirm this happens on the latest version of Paragraphs?
Comment #6
kporras07 commentedHi,
I confirm this is still an issue. I'm able to reproduce it the same as OP.
Paragraphs: 1.12
Drupal core; 9.2.4
Comment #7
avpadernoDrupal 8.9.x is now open only to security issues.
Comment #9
thomas.frobieterGood to see, we're not alone with this extremely disturbing issue.
The worse thing about this issue is, that you can't save the node afterwards. So all modifications are gone, you need to reload and startover.
I can't confirm the reproduction from the OP, maybe because we are using the experimental widget and i am not able to click the second 'delete' fast enough.
However, I'm not exactly sure when this happens with our configuration. I have videos from customers (8.x) where this problem appears, but I wasn't able to reproduce it the same way. But yeah .. it also happened to me very often, its some combination of creating & deleting paragraphs (maybe just specific bundles). So ..probably some kind of race condition.. i will keep watching this, hopefully i will be able to find a reproducible case.
And it still happens with our Drupal 9 configuration using layout_paragraphs, so this is still a thing..
Comment #10
avpadernoComment #11
anybodyJust had a look at this and guess it's either
a) entity_browser bug
or
b) paragraphs + entity_browser bug
It's hard to reproduce but in certain combinations when we click a paragraph "Edit" we expect the paragraph edit modal, but the server returns the entity_browser modal, while the triggering element in the request is the paragraph edit button correctly:


So it seems like the Media Browser "thinks" it should open and returns it ajax command instead of the paragraph edit, which should happen... strange!
"Auto open entity browser" is NOT enabled for any entity browser on our page.
Searched the entity_browser issues for possibly related issues:
#2857339: Modal auto-open conflicts with AJAX
#3045723: Entity browser with auto open opens on field settings form
#2897855: Entity browser modal dialog opens by pressing enter in any text field
#3008700: Prevent "auto_open" infinite loop
Comment #12
anybodyFurthermore I can confirm the modal, which is triggered (twice) is the same and is an media entity image field from the node entity (not from a paragraph). Like the original author wrote.
Comment #13
anybodyJust had the same in a different project where we use Media in Core and layout_paragraphs combined with image fields on the node entity using the media library widget.
When editing paragraphs sooner or later the node entity image field media library widget pops up with the following action:
action="/de/media-library?media_library_opener_id=media_library.opener.field_widget&media_library_allowed_types%5Bimage%5D=image&media_library_selected_type=image&media_library_remaining=1&media_library_opener_parameters%5Bfield_widget_id%5D=field_coverimage&media_library_opener_parameters%5Bentity_type_id%5D=node&media_library_opener_parameters%5Bbundle%5D=page&media_library_opener_parameters%5Bfield_name%5D=field_coverimage&media_library_opener_parameters%5Bentity_id%5D=86&media_library_opener_parameters%5Brevision_id%5D=1616&hash=xx"
Any ideas?
The strangest thing for me is now, that it's NOT only media entity browser, but also media library browser widget, which shows this problem.
It can't be cleanly reproduced. After reloading the page and doing the same steps again, it doesn't happen. Then sooner or later it happens again, so it seems to have some kind of "state". Any ideas to find the reason would be highly appreciated.
Comment #14
anybodyOkay, we're one step closer... I debugged that down and the Modal seems to appear as a result of this Exception in
web\core\lib\Drupal\Core\Form\FormBuilder.php:
Here's a screenshot of the backtrace I took in buildResponse() from the unwanted modal and the request:


I'm not sure yet, if that Exception is a result or the cause of the problem.
Comment #15
anybody@larowlan: This was really hard to reproduce and track down, but now I think I have some interesting results, so we should decide how to proceed here:
1. This seems like a race condition bug for (Modal) commands in core. It currently does NOT seem to be DIRECTLY caused by any of: Media, Media Library, Entity Browser, Paragraphs or Layout Paragraphs! But as a result, the Modals of Media Library / Entity Browser / ... are triggered! And a module which uses Modals a lot, like Paragraphs is likely to be affected by this issue. So there's a good chance to run into this, if you're using a combination of these modules.
This also explains why it happens in so many different combinations, as listed above... in Drupal 8, Drupal 9, with media library or with entity browser, etc...
2. The issue (at least for (layout) paragraphs appears when CLOSING a modal (or clicking "cancel" which is the same action) and very fast open another modal. If you do this open-close-open-close repeatingly very fast on a page with several paragraphs, the bug is likely to appear. The amount of (paragraphs) items seems to increase the chance for this to happen, perhaps because the client or server requires more time for processing.
The _triggering_element_name is "cancel":
_triggering_element_name: cancelfor the second (wrong) modal.3. The difference between the expected AJAX response and the actual race condition response can be seen in the following example.
What we'd expect are the two commands:
Expected (returned when clicking slow and waiting 2-3 seconds between each click):
Actual result of closing the dialog (race condition):
which insteads runs 5 commands:
but misses
Both times the request is the same!
The only difference between each call is the form_build_id, which I guess is expected!
Comment #16
anybody(Sorry for the noise here, but I'm trying to document all the checks and steps for others to hook in here fur further investigations):
I digged deeper and had a look where the openDialog command comes from and debugging shows that for example when using the media library widget, the open_button #ajax callback is triggered in case of the racecondition:
so that MediaLibraryWidget::openMediaLibrary() is being executed. As far as I can tell (if ajax didn't kill my debugging event listeners) there is no UI Event on the trigger, so that this seems to be wrongly detected server-side.
I backtraced the call triggered from the "Modal close / cancel" in MediaLibraryWidget::openMediaLibrary() and had a look at the request handled by the kernel.

As you can see the request looks like expected, but the "query" contains the unexpected media library call:
The Media Library Widget was NEVER CLICKED! So where can that part come from?
Comment #17
anybodySearched for further issues which MIGHT be related and found: #3066447: [random test failure] Random failures building media library form after uploading image (WidgetUploadTest) which is far from being clearly related, but both have some things in common, so I think it would make sense to check that?
Anyway, we shouldn't forget that using Drupal 8 + Entity Browser Widget had the same issue as Media Library Widget, but perhaps they're both simply based on the same #ajax or base class logic.
I'm at the end of my latin here... (no idea if that DE term exists in English ;D) we need Core Maintainers look at this.
Comment #20
jefuri commentedI debugged it as well. And what I saw is that the triggering element was not found.
So you submit a form with the triggering element information. In the form handling it searches for the element that was triggered the submit. But it was not found.
What then happens is dat het searches for another button, the first button in the list of possible triggering elements in the form.
FormBuilder->processForm()
FormBuilder->DoBuildForm()
In this case when I was debugging, the first button was the media library button. And that is why that is command is being returned.
Comment #22
heikkiy commentedWe have been struggling and debugging this issue for a couple months also. We have two different paragraph fields in the node edit form and it seems to behave exactly the same as described in the comments in this issue.
It seems like it is the combination of Paragraphs and Entity browser which results in the bug because in another project we have a similar setup but without Entity browser and we haven't encountered the same issue there. We also tested that we can reproduce the issue with Media Library in addition to Entity Browser.
Sending the Ajax call seems to return the wrong element it replaces the wrong paragraph after the element is added. I originally reported the issue to Paragraphs module https://www.drupal.org/project/paragraphs/issues/3356796 and there is also a video recording of the effect.
I feel like this issue should have a higher priority because even though it can be hard to reproduce it breaks the content input and node edit form largely and also results in loss of data when it happens.
EDIT: I used a bit more time in the another project and I was able to reproduce the issue there. Interesting enough in the first project we got reports of the issue after 1 month but the other project has been running several years without reports from users. But the symptoms are the same and it's easiest to reproduce the issue by quickly removing a paragraph and then before the Ajax call is finished you click on collapse.
The first project is using Gin, Media library and Entity Browser. The second project is using Claro and Media library without Entity Browser even being installed.
Comment #23
anybodyComment #24
anybodyComment #25
andyrigby commentedWe've just experienced this issue, but it was reproducible each time on a particular Paragraph "Remove" button.
The node edit form was large; lots of paragraphs, fields, meta tags, schema.org metatags etc.
The issue was the
_triggering_element_namewas not present in the POST variables, even though it was sent by the browser.We needed to increase the
max_input_varsphp setting from 1000 to 1200 (in our case)This resolved it for us.
Comment #26
heikkiy commentedI checked our PHP settings to check the solution from #25. In our case max_input_vars is already set to 5000 but we are still experiencing the original issue. It is of course possible that our paragraph and node forms with multiple tabs are so large that even 5000 is not enough to hold the original variable.
@andyrigby could you give more detailed instructions how you tested that the _triggering_element_name is not present in the POST variables? I could try playing around with our test environment to see if I can reproduce the problem with our current settings and if raising the limit would help.
Comment #27
heikkiy commentedWe tested increasing the max_input_vars to 10 000 but were still able to reproduce the issue. In our case it happens that if you are too quickly opening and closing a media modal it gets replaced by a paragraph element. It seems like the reason is that the previous modal request isn't completed when the next one starts so it seems like a race condition. It took us approximately 4-5 clicks of opening and closing the modal to get the wrong form displayed.
Comment #28
super_romeo commentedComment #29
ludo.rWe're experiencing this issue also on Drupal 10.2.8.
Seems also that when this happens, content is lost upon save.
I think this should be major issue.
Comment #30
bkosborneI added #3495881: Firefox retains form_build_id on form reloads, causing old form cache entry to be used and creating weird behavior for the Media Library widget which I think might be related to this.
Comment #31
grevil commentedI just ran into this issue while working at #2772279: Seamless entity reference autocomplete integration.
For us, this issue is not 100% reproducible. We have a massive edit form with a LOT of fields. This exact issue happens inside a paragraphs field which references a paragraph with the upcoming entity browser widget developed in #2772279: Seamless entity reference autocomplete integration (with cardinality 1). When pressing the "Remove" button, sometimes (not always) the referenced entity won't get removed and instead the media library gets opened.
I step debugged into MediaLibraryWidget::openMediaLibrary() and interestingly enough it triggers, when pressing the "Remove" button. The triggering element is also the "media-library-open-button" for some reason, so it seems to mess up the triggering element.
Although when I check the triggering element through the user input, I get the actual "remove-button" as my triggering element.
Now through comparing these values, we can return an AjaxResponse without the "OpenModalDialogCommand" early, if these names don't match. Unfortunately, this leads to the form not removing the entry properly, meaning the AJAX is not doing anything anymore. Meaning the issue has to happen before "openMediaLibrary" is called, but an interesting observation non the less.
Our "max_input_vars" is already at 5000 and the correct "_triggering_element_name" is part of the POST (as seen through `$form_state->getUserInput()['_triggering_element_name']`).
I also found out, that when the issue doesn't appear, we enter this if state:
But when the remove button would usually open the media library (the incorrect behavior), it doesn't go into the if state, because this if state:
returns FALSE, as the triggering element name is different from the element name, as the id is slightly different:
$input['_triggering_element_name'] = ''field_x_remove_1001384_0_bBhuaWAbk6TuBnwUG0wh3JIEtpaaBJHXGeoF07Or3iQ''
$element['#name'] = 'field_x_remove_1000020_0_bBhuaWAbk6TuBnwUG0wh3JIEtpaaBJHXGeoF07Or3iQ'
(The ID differs)
But this could be related to the widget implementation.
Comment #32
frazile commentedSeems we ran into this with nested paragraphs (drupal 10.5).
When collapsing or editing a nested paragraph Drupal randomly opens the media library instead.
Sometimes it also adds some random paragraph (that shouldn't even exist as a nested option) into the parent paragraph.
Easiest way to reproduce this has been to open and close and edit the nested paragraphs fast, but this has happened even when editing in a reasonable pace.
Comment #34
matthiasm11 commentedA possible solution can be found in #3617898: Form cache is deleted after a submission that never actually executed (e.g. an Ajax-only button), stranding the form's cached state and #3617904: A nested entity form's field widget calling $form_state->setCached(FALSE) unintentionally disables caching for the parent form.
Comment #37
valegole commentedWhen Core cannot identify the clicked Ajax button, it no longer blindly uses the first button. It uses the button whose unique name was posted with the request. Only if that name is missing or used more than once does it still fall back to the first button.
Comment #38
smustgrave commentedCan we get a test case showing the problem please.
Also summary needs to include what the proposed solution is.
Also was #34 tested if it fixes the issue?
Comment #39
valegole commentedI tested the patch from #34 against this issue. It does not fix it: without the additional change in FormBuilder::doBuildForm(), Drupal still falls back to the first button, so the wrong triggering element is used.
Comment #40
oily commentedComment #41
oily commentedTest coverage is now in place. Ran the test-only test and it fails on the new test coverage.