Hello,
I found this bug when creating a new node which has an entity reference field to other type of nodes that also have an entity reference field to nodes. It seems to occur only when a certain order of steps are made, but it is quite simple to reproduce it.
We have a content type (let's assume Basic Page) with a multivalued field called Components, which is an entity reference to Content, allowing a sort of content types (for this explanation, let's assume Tabs and Free Form types). Content type Tabs also has the same field Components. The field Components is configured to use "Inline Entity Form - Complex" widget for both Basic Page and Tabs content types. The idea here is to create a Basic Page node which has a tabbed structure of Free Form elements. The bug occurs when the editor executed the following steps:
1. On "Create Basic Page" page, add a new Tabs node into Basic Page's field Components.
2. While filling Tabs' node fields, and before saving it, add a Free Form node into Tabs' field Components.
3. After filling all required fields of the Free Form node, save it clicking on its "Create node" button, then also save the Tabs node clicking its respective "Create node" button.
4. Without saving the Basic Page node, click to "Edit" the Tabs node that has just been saved, and add a new Free Form node to the Tabs' field Components. Click on "Create node" to save the new Free Form node, then click on "Update node" to save the Tabs node.
5. Click to save the Basic Page node.
The following fatal error will occur:
Drupal\Core\Entity\EntityStorageException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '3bda65d4-410d-47ba-b4ff-ff2843f04085' for key 'node_field__uuid__value': INSERT INTO {node} (vid, type, uuid, langcode) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3); Array ( [:db_insert_placeholder_0] => [:db_insert_placeholder_1] => free_form [:db_insert_placeholder_2] => 3bda65d4-410d-47ba-b4ff-ff2843f04085 [:db_insert_placeholder_3] => en ) in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 846 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).
Drupal\Core\Database\Statement->execute(Array, Array) (Line: 634)
Drupal\Core\Database\Connection->query('INSERT INTO {node} (vid, type, uuid, langcode) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3)', Array, Array) (Line: 357)
Drupal\Core\Database\Driver\mysql\Connection->query('INSERT INTO {node} (vid, type, uuid, langcode) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3)', Array, Array) (Line: 32)
Drupal\Core\Database\Driver\mysql\Insert->execute() (Line: 973)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->doSaveFieldItems(Object) (Line: 665)
Drupal\Core\Entity\ContentEntityStorageBase->doSave(NULL, Object) (Line: 457)
Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 837)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object) (Line: 395)
Drupal\Core\Entity\EntityBase->save() (Line: 265)
Drupal\inline_entity_form\Form\EntityInlineForm->save(Object) (Line: 70)
Drupal\inline_entity_form\WidgetSubmit::doSubmit(Array, Object)
call_user_func_array(Array, Array) (Line: 109)
Drupal\inline_entity_form\ElementSubmit::doSubmit(Array, Object) (Line: 79)
Drupal\inline_entity_form\ElementSubmit::trigger(Array, Object)
call_user_func_array(Array, Array) (Line: 112)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 52)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 591)
Drupal\Core\Form\FormBuilder->processForm('node_page_form', Array, Object) (Line: 320)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 91)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 573)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 151)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
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: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 84)
Drupal\shield\ShieldMiddleware->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 694)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
I started debugging a little bit on the way IEF saves the content created there, and I noticed that nodes aren't created on each click on "Create node" buttons, but they are all created in the end. The error happens because when the editor created and then updated the Tabs node on the save operation (i.e. on the same "Create Basic Page" operation), IEF tries to create twice the first child. At that moment of the execution, the entity object is considered new, which triggers the function of creation instead of update in the second occurrence. Its UUID is found in table node, which triggers the fatal error above.
I found the following issue that seemed similar, but since the version of IEF is not the same, and the trace is different, I chose to create a new issue.
I wrote a patch where I changed function WidgetSubmit::doSubmit to check if the UUID already exists in table node, and if so ignore it. I'll add the patch on my next comment here.
Regards,
Mauricio M. Silveira
| Comment | File | Size | Author |
|---|
Issue fork inline_entity_form-3105952
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
maursilveira commentedHere is the patch for the reported issue. I initially reverse the IEF entities to ensure we get the latest version of each node first to be saved. Then, I create a temporary array where each UUID will be stored. For each entity that is going to be saved, I check if its UUID exists in the temporary array. If not (i.e. this is the first occurrence of that entity), the UUID is added to the array and the entity is saved normally. If the UUID is found in the array (i.e. that is not its first occurrence), the entity is unset and not saved.
Please let me know if there's any question about the patch, or how to reproduce the issue. Thank you.
Regards,
Mauricio M. Silveira
Comment #3
geek-merlinMy gut feeling is that this one is a duplicate of the other issue. Can you check if with the other fix you can reproduce your problem?
Comment #4
maursilveira commentedHi @geek-merlin, thanks for your reply!
Do you think the issue I reported is the same reported in 2653574? I didn't read the whole other issue yet, but I'm not so sure. They might be caused by the same "source", but the description of the other issue (specifically the steps to reproduce) are quite different than the ones I did and described here. Even though, I'll definitely check if the fix there solves this issue I reported.
Just to be sure, do you want me to try the patch on comment #141?
Thank you!
Comment #5
geek-merlin> Just to be sure, do you want me to try the patch on comment #141?
Yes.
Comment #6
maursilveira commented@geek-merlin, I removed my previous patch, returning to original IEF code, then applied patch on comment #141 of issue 2653574, as you recommended.
Unfortunately, that patch doesn't solve the bug I reported, and I got the same fatal error I pasted on the description of this issue. When I re-applied my patch, the error no longer occurred, with or without that patch from the other issue.
Please let me know if you need more information about this, or if you want me to try anything else.
Thank you.
Comment #7
geek-merlinThanks that you cross-checked this is not the same.
I assume this did not change on dev (please always check and file against dev in the future).
This is really a strange thing. Let's re-phrase and guess a bit: So this happens when you "create, save, edit, save" an IEF child entity in the UI, and somehow IEF internally memorizes it should save twice which leads to errors.
While the patch may solve the problem, it does not go to the root. Questions:
a) If the above is correct, the error can be reproduced mush simpler. Is this correct? What is the simplest form to reproduce it?
b) If the above is correct, where is the place IEF internally saves the entity twice (i guess into $formState), so we can fix that?
Can you wirte a failing test for a)?
Comment #8
maursilveira commented@geek-merlin Sorry for the late response.
So, basically the error happens when, using IEF for a nested structure of entity references, I do:
1. Create parent
2. Create first child (entity reference in the parent)
3. Save first child
4. Save parent
5. Edit parent
6. Create second child
7. Save second child
8. Save parent
9. Save main node (a Page, for example).
You're right, IEF marks the first child to be saved twice. On the attached screen shot you can see the structure of the
$form_state->get('inline_entity_form'):The first array element (key
'493d0c383f7036411b16c0bc88082c98ac9ac735') has one entity inside 'entities', which is the parent entity (following the structure cited on my first comment, the "Tabs" element).The second array element (key
'2c2aadfb2a740718ba1b50df0a5f56e50a39104d') also has one entity, which is the first child (the first Free Form entity created and saved).The third array element (key
'9ff53622379d8cb098d6a86ebc14d4b1312f261c') has two entities, which are both child entities (first child with weight 0, second child with weight 1). Notice that first child is set to be save twice, in the second and third IEF arrays elements.I agree with you that this patches doesn't solve the issue on its origin, which it could probably be better. However, I'm struggling a little to find exactly where this should be fixed instead, if it should be in
Drupal\inline_entity_form\ElementSubmit::doSubmitor in some of the other functions called as callback that happen just beforeDrupal\inline_entity_form\WidgetSubmit::doSubmit(where I made my fix).I'd appreciate any ideas to help me here. Thank you!
Comment #9
staceroni commentedWe have a nested entity structure and we are using IEF to create/edit these entities. We are intermittently seeing this error; About 1 out of every 5 times.
We are on Drupal 8.8.10 and IEF version 1.0.0-rc7.
Parent entity has 2 entity reference fields; Create one entity reference. That entity has another field to link to an existing or create a new entity. Create a new reference. Therefore you have created 3 nested entities. When you save, you get a fatal error
Integrity constraint violation: 1062 Duplicate entry 'ab497f6c-4bf2-4b72-b053-30d170b2f0b0' for key 'entity_field_uuid_value'
I will check trying this patch sometime soon.
Stacey
Comment #10
ivavictoriaJust leaving a note that we're seeing this error as well. The patch seems to prevent the error.
In case it helps anyone, here is a generalized description of how to consistently reproduce the error:
Assuming this structure of nested entities:
Parent entity > child entity > grandchild entity
Steps to reproduce:
1.) Create/edit a parent entity.
2.) Create a new child entity. Add a grandchild entity to it. Click the ‘Create [child entity]’ button.
3.) Before saving the parent entity, re-edit the child entity and add another grandchild to it. Click the ‘Update [child entity]’ button.
4.) Then save the parent entity. The fatal error occurs.
Comment #11
anairamzapHi, we were getting the same error but with "heavy" nested taxonomy terms. In our case we have 4 levels (!):
- Node: parent entity --> Using Inline entity form.
-- Entity Reference to Media: child entity
--- Entity Reference to Node: grand-child entity
---- Entity Reference to Taxonomy Term: great-grand-child
Applied the patch provided in #2 and I can confirm it solves the issue, no fatal error thrown for "Duplicate Entry".
What needs to be done in order to make this RTBC?
Thanks!
m
Comment #12
than_nak87 commentedAfter applying the suggested patch, some php notices started to appear in our log messages.
Notice: Undefined index: #field_name in inline_entity_form_open_form() (line 209 of inline_entity_form.module)
Also, some users complain that when the hit the "Add more" button, a new form doesn't open and the inline form becomes useless. They need to refresh their page. Not sure, if these two related.
Also, both the log file and the "Add more" button not opening happen rarely, not sure how to reproduce this...
Comment #13
spokjeI've created a failing test for this one.
This seems to only happen when there's at least one parent->child->grandchild in play (so triple nested).
I couldn't reproduce it with only parent->child relations as suggested by @geek-merlin here:
The minimal steps to reproduce this error are (at least for me) described here by @maursilveira:
(Note: First create a node that holds the parent)
Comment #14
spokjeAlthough patch #2 does make the newly added failing test pass, I'm keeping this at
Needs work.The comments in #12 seem to point out that "somehow sometimes" this patch is un-setting too much.
I think we should try to look a bit deeper into the root cause of this one.
Looking at @geek-merlin... 😇
EDIT: As already excellently "Sherlocked" in #8 when the node isn't saved before adding a new child to a parent the first (and most probably n-th child when adding a n+1-th child through editing the parent before saving the node) is marked as `needs_save` more than once.
Patch #2 does house-keeping on doSave to try to repair it all, but I think we should "somehow" prevent the n-th child from becoming marked as `needs_save`.
Intermittently looking into that, but I've seem to become too much specialized in writing tests for IEF to immediately grok it's actually logic.
If anybody sees where it all falls down: Please help :)
Comment #15
geek-merlin@Spokje: Thanks for soft-pinging me. Unfortunately i have the same concerns about this concerning our saving-nested-entities code that i voiced in the related issue... Still thinking...
Comment #16
than_nak87 commentedI've modified a little bit the patch from #2 to unset the needs_save flag of a duplicate entity (based on uuid) instead of unsetting the entity itself, which was probably causing the warnings described in #12.
Since I have never experienced again with the ief code, the idea of unsetting the needs_save flag was based on #14 EDIT comment.
Not sure if this is the best way to handle it, but the issue seems to be resolved, although it doesn't solve the root cause of the issue.
Comment #17
pgshehata commented#16 patch no working for me
Same error with a new duplicate entry
Comment #18
geek-merlinWe now have multiple "dragons in nested IEFs" issues...
Comment #19
geek-merlinComment #20
geek-merlinComment #21
geek-merlinComment #23
geek-merlinOK, 57c5 successfully triggered the exception. Let's see if this is green.
Comment #24
geek-merlinBanzai! We provoked the multiple-child variant of the bug**.
Comment #25
geek-merlinOK, and now the improved fix.
Comment #28
geek-merlinFinally all green, mustfail is red. So ready.
Comment #30
geek-merlin