Problem/Motivation
Steps to reproduce:
1. Create a new user
2. Add a new paragraph to an existing node with that user and save.
3. Delete the user
4. Try to save the node with a different user.
Result: The referenced entity (user: X) does not exist validation error.
No way to fix it.
This affects the uid and also the revision uid, including all existing revisions.
Proposed resolution
I never understood why we even have a uid and revision_uid field anyway, there's not really a use case for that to be different than the host. There's no way to change/control it through the UI.
Remove it, fall back to the parent entity for if called? Not sure if we can get away with that under BC.
Alternatively, we could also implement hook_user_cancel()/ delete().
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #41 | 2994286-paragraphs-uid-failure-41.patch | 1.23 KB | penyaskito |
| #34 | interdiff-2994286-27-34.txt | 879 bytes | johnchque |
| #34 | paragraphs_validation_can_fail-2994286-34.patch | 9.75 KB | johnchque |
| #27 | interdiff-2994286-25-27.txt | 592 bytes | johnchque |
| #27 | paragraphs_validation_can_fail-2994286-27.patch | 9.68 KB | johnchque |
Comments
Comment #2
miro_dietikerI would vote to drop them..
The field is also not exposed in the field UI and thus can not be configured for display or so.
And we do not officially support complex Paragraph views so i don't fear there's risk people output this uid field in Paragraph views and we destroy the views.
And we will still implement the interface and can return the host entity uid instead.
So i don't see yet any true promise we break.
While doing those changes to avoid too many storage changes - it would be good to add the missing parent revision reference field as well.
#2949412: Nested paragraphs automatically publish, even if the parent is a draft and child issues...
Comment #3
seanbJust ran into this. I also can't think of any reason why we should record an extra copy of the uid / revision_uid? +1 for removing the fields.
Comment #4
berdirNot sure why set to minor.
Comment #5
miro_dietikerAdded this to the #2954487: New Roadmap
Comment #6
arpad.rozsa commentedRemoved the uid, revision_uid fields and changed the related getters and setters.
Comment #8
berdirNext step is an update function, what you need to do there is truncate the fields first in the data and revision table and then uninstall the field storage definition, see path_update_8200() for example.
Comment #9
arpad.rozsa commentedAdded the update function, but when I wanted to uninstall the revision_uid field storage, I got an error, if it had data in the database, so I ended up truncating the both of the fields, just in case. Also fixed the failing test.
Comment #10
berdirthis is a bit strange as we actually don't care about tables here but it will run twice for the "uid" field. so maybe run it over array_unique($table_fields) or so?
Wouldn't fail as it checks if the field storage definition is installed but that would be a bit cleaner.
Comment #11
arpad.rozsa commentedYeah good catch, wouldn't hurt, but it is better this way.
Comment #12
miro_dietikerTechnically there is a moment when the Paragraph is saved and the parent is not yet set.
You can see the valid state here also:
Not caring about this case could cause a fatal error in special cases.
Looks like we also need to fix the interface with |null.
Comment #13
berdirAgree, we need to check, but we can just use if ($this->getParentEntity()) for that, no need to duplicate the specific checks and then it would also cover weird cases where the entity doesn't exist anymore...
Comment #14
arpad.rozsa commentedAdded the checks for the parent entity to the getters. Also added a hook to remove the content_translation_uid from the base field definitions, so if the content_translation module was enabled it doesn't give the user an error that the content_translation_uid field is missing from the database and it won't try to insert data into that column in the future.
Comment #15
miro_dietikerThis needs a new update number.
Nitpick, but this always calls getParentEntity twice and there's quite some complexity with it. Let's try to call it only once.
Maybe invert the logic...
Comment #16
berdirComment #17
arpad.rozsa commentedChanged the update number and the parent entity checking.
Comment #18
berdirLooks good now I think.
Comment #19
howards commentedI noticed some irregularities after using this patch against 8.7.x drupal core. The circumstance is a paragraph fieldset added to a taxonomy vocabulary whereby the paragraph may add taxonomy terms to the same vocabulary.
In this setup the taxonomy term created had no initial referenced paragraph created, and then was initially saved/created without the reference. If the term (with no initial referenced paragraph) is later edited to add a referenced paragraph, clicking on "Add paragraph" results in javascript errors.
The server error log contained this text:
The offending code out of ContentEntityBase.php is the following:
Unfortunately I do not have the expertise to trace the code back to the origin causes, but it appears as though field definitions were changed in the way that owners were fetched by the parent entity? I am not sure if there was some place that was missed in changing the way ownership was set or...
An issue or not?
Comment #20
howards commentedRemoving RTBC in favor of needs work. The reproduction of the issue:
Copy and paste this into a debugParagraphs.make file:
Then do the following:
$ drush make debugParagraphs.make docroot ; cd docroot ; composer install ; drush si -y standard --account-name='admin' --account-pass='admin' --db-url='mysql://your_user:your_pass/your_database' ; drush en -y field_ui paragraphsOnce the installation has completed:
mkdir ../database ; drush sql-dump > ../database/debugParagraphs.sql/admin/structure/paragraphs_type/addand add a new paragraph type./admin/structure/types/manage/article/fieldsand add a field referencing the paragraph just created./admin/structure/taxonomy/manage/tags/overview/fieldsand add a similar field referencing the exact same paragraph.drush cex -y(My "sites" folder is outside thedocroot, and are automatically re-linked when I run a custom drush script to rebuild the code of the site.)Once the backup of the database is made, and the sites directory is out of the docroot and symlinked, it makes recreation of the bug easy.
Afterward, I reimported the initial database and imported the configuration changes, I went and created an article using a Test Tag in the paragraphs field. Afterward, I went to
/taxonomy/term/1/editand added a new paragraph option with another tag. Worked like a charm.Then I went and uncommented the "patch" line and the patch itself in the debugParagraphs.make and rebuilt the code base. Then I reimported the initial database and the configuration that was saved. I repeated the process above and was unable to add another tag in the paragraph field after going to
/taxonomy/term/1/editbecause it threw errors similar to the ones outlined in the previous comment.Hopefully, this sheds a bit more light on where the errors are coming from?
Comment #21
berdirThanks for the feedback. That's basically exactly what I was worried about, but it's something that we haven't yet been able to reproduce.
What would be really helpful is if you could provide a backtrace, that's most likely already enough to pinpoint the problem instead of having to set up a relatively complex site.
Enable verbose error logging on your site, then you should see a long error that shows exactly what/who is calling it like that.
Comment #22
howards commentedIs this what people are after?
The website encountered an unexpected error. Please try again later.InvalidArgumentException: Field uid is unknown. in Drupal\Core\Entity\ContentEntityBase->getTranslatedField() (line 587 of core/lib/Drupal/Core/Entity/ContentEntityBase.php).
Drupal\Core\Entity\ContentEntityBase->get('uid') (Line: 253) Drupal\paragraphs\Entity\Paragraph->getOwnerId() (Line: 110) Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget->formElement(Object, 0, Array, Array, Object) (Line: 335) Drupal\Core\Field\WidgetBase->formSingleElement(Object, 0, Array, Array, Object) (Line: 202) Drupal\Core\Field\WidgetBase->formMultipleElements(Object, Array, Object) (Line: 104) Drupal\Core\Field\WidgetBase->form(Object, Array, Object) (Line: 171) Drupal\Core\Entity\Entity\EntityFormDisplay->buildForm(Object, Array, Object) (Line: 650) Drupal\paragraphs\Plugin\Field\FieldWidget\InlineParagraphsWidget->formElement(Object, 0, Array, Array, Object) (Line: 335) Drupal\Core\Field\WidgetBase->formSingleElement(Object, 0, Array, Array, Object) (Line: 831) Drupal\paragraphs\Plugin\Field\FieldWidget\InlineParagraphsWidget->formMultipleElements(Object, Array, Object) (Line: 104) Drupal\Core\Field\WidgetBase->form(Object, Array, Object, NULL) (Line: 942) Drupal\paragraphs\Plugin\Field\FieldWidget\InlineParagraphsWidget->form(Object, Array, Object) (Line: 171) Drupal\Core\Entity\Entity\EntityFormDisplay->buildForm(Object, Array, Object) (Line: 125) Drupal\Core\Entity\ContentEntityForm->form(Array, Object) (Line: 94) Drupal\taxonomy\TermForm->form(Array, Object) (Line: 117) Drupal\Core\Entity\EntityForm->buildForm(Array, Object) call_user_func_array(Array, Array) (Line: 518) Drupal\Core\Form\FormBuilder->retrieveForm('taxonomy_term_tags_form', Object) (Line: 275) Drupal\Core\Form\FormBuilder->buildForm('taxonomy_term_tags_form', Object) (Line: 93) Drupal\Core\Controller\FormController->getContentResult(Object, Object) call_user_func_array(Array, Array) (Line: 123) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 582) 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: 99) Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78) Drupal\page_cache\StackMiddleware\PageCache->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: 669) Drupal\Core\DrupalKernel->handle(Object) (Line: 19)Comment #23
berdirYes, that's what I need. I can see two things in that backtrace:
a) Not the problem for this issue, but you seem to be using paragraphs in combination with the core autocomplete widget? That's not supported because paragraphs are not designed to be re-used, they must only have one parent, otherwise some things like private file access will not work correctly. It's also risky with the work we're doing in ERR to clean up unused paragraphs.
b) The real issue here is that the getOwnerId() call still seems to be accessing the uid field. Not sure if you removed the patch again or incorrectly applied it, but that's not supported and not what the code is doing when this patch is applied. You can not remove patches again that make structure changes. Also, you should be very-very careful in any patches that have update functions, because there is a chance that these patches will be rerolled with different update function numbers and then your site is going to be very broken as it will not run certain updates.
Comment #24
johnchqueWe need one more update function. Working on that.
Comment #25
johnchqueWe needed to update the metadata keys too. :)
Comment #27
johnchqueThis is needed, thanks @Berdir.
Comment #30
berdirTest fails are unrelated but lets open an issue to fix them. new update function looks good lets get this in.
Comment #31
johnchqueTests will be fixed here #3026890: Update to Entity Browser 8.x-2.x in tests
Comment #32
mbovan commentedI was subscribed to this issue.
I think
isset($revision_metadata_keys['revision_uid'])should beisset($metadata_keys['revision_uid']).Comment #33
berdirTrue, missed that. And we should also unset the key and then set $metadata_keys.
Comment #34
johnchqueSure, I think this should address both comments above. Thanks for noticing. :)
Comment #36
johnchqueComment #38
berdirCommitted.
Comment #39
penyaskitoThis is making Lingotek tests fail, I'm still looking at the reason.
Comment #40
penyaskitoSo actually fails when calling getOwner in embedded paragraphs. We cannot assume there is an "uid" field.
This is not ideal, but at least better and works for me.
Comment #41
penyaskitoSimplifying this by @Berdir suggestion on Slack.
Comment #42
berdirComment #44
berdirThanks for catching that so quickly, somehow read over that prat.
Comment #45
penyaskitoAwesome, thanks!
Comment #47
pasqualleHow could I see this error with paragraphs version 8.x-1.6?
Comment #48
berdirThis change is not in 8.x-1.6, you still need the patch if you had that applied. 8.x-1.6 was only a security fix, based on 8.x-1.5.
Comment #49
pasqualleI see. I was on the dev version, run these updates, then switched to 1.6.
Switching back to dev..
Thanks
Comment #50
trevorbradley commentedI'm having issues with this patch/Paragraphs 1.7/1.8 - I can't delete paragraph fields with content anymore! See #3044256: Unable to delete paragraph fields without error