So this issue is on the intersection between Paragraphs module and Inline Entity Form. Adding it here as the error message is returned due to code belonging to Paragraphs module.

I have a following structure: Node -> Paragraph -> Media entity. Paragraphs entity revision field is using Experimental widget. Media entity is using Inline Entity Form - Simple. Media field has cardinality 1, while Paragraph field - unlimited. Steps to reproduce:

  1. Create new node (or edit existing one).
  2. Add new Paragraph
  3. Upload file into Media field
  4. Collapse yet-unsaved Paragraph, so you don't see fields
  5. Submit the form
  6. The website encountered an unexpected error. Please try again later.

Here's the screencast:
Only local images are allowed.

The error:
LogicException: Form errors cannot be set after form validation has finished. in Drupal\Core\Form\FormState->setErrorByName() (line 1057 of /home/dmv92/www/core/lib/Drupal/Core/Form/FormState.php).

And the code that is responsible for this error was added in #2939718: Remove validation of closed paragraphs, fix validation and display of validation message for collapse (ParagraphsWidget:massageFormValues()):

        // Assume that the entity is being saved/previewed, in this case,
        // validate even the closed paragraphs. If there are validation errors,
        // add them on the parent level. Validation errors do not rebuild the
        // form so it's not possible to auto-uncollapse the form at this point.
        elseif ($form_state->getLimitValidationErrors() === NULL) {
          $violations = $paragraphs_entity->validate();
          $violations->filterByFieldAccess();
          if (count($violations)) {
            foreach ($violations as $violation) {
              /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */
              $form_state->setError($element[$item['_original_delta']], $violation->getMessage());
            }
          }
        }
CommentFileSizeAuthor
#13 3013171-13.patch1.39 KBmheip
#5 3013171-5.patch883 byteszaporylie

Comments

zaporylie created an issue. See original summary.

zaporylie’s picture

The backtrace to confirm why I think the code above is to blame here (I highlighted relevant lines):

ParagraphsWidget.php:2226, Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget->massageFormValues() <---------------------
WidgetBase.php:381, Drupal\Core\Field\WidgetBase->extractFormValues()
ParagraphsWidget.php:2267, Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget->extractFormValues()
EntityFormDisplay.php:225, Drupal\Core\Entity\Entity\EntityFormDisplay->extractFormValues()
ContentEntityForm.php:338, Drupal\Core\Entity\ContentEntityForm->copyFormValuesToEntity()
EntityForm.php:304, Drupal\Core\Entity\EntityForm->buildEntity()
ContentEntityForm.php:159, Drupal\Core\Entity\ContentEntityForm->buildEntity()
EntityForm.php:289, Drupal\Core\Entity\EntityForm->submitForm() <-------------------------
ContentEntityForm.php:149, Drupal\Core\Entity\ContentEntityForm->submitForm()
FormSubmitter.php:111, call_user_func_array:{/app/core/lib/Drupal/Core/Form/FormSubmitter.php:111}()
FormSubmitter.php:111, Drupal\Core\Form\FormSubmitter->executeSubmitHandlers()
FormSubmitter.php:51, Drupal\Core\Form\FormSubmitter->doSubmitForm()
FormBuilder.php:589, Drupal\Core\Form\FormBuilder->processForm()
FormBuilder.php:318, Drupal\Core\Form\FormBuilder->buildForm()
FormController.php:93, Drupal\Core\Controller\FormController->getContentResult()
EarlyRenderingControllerWrapperSubscriber.php:123, call_user_func_array:{/app/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php:123}()
EarlyRenderingControllerWrapperSubscriber.php:123, Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
Renderer.php:582, Drupal\Core\Render\Renderer->executeInRenderContext()
EarlyRenderingControllerWrapperSubscriber.php:124, Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
EarlyRenderingControllerWrapperSubscriber.php:97, Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
HttpKernel.php:151, call_user_func_array:{/app/vendor/symfony/http-kernel/HttpKernel.php:151}()
HttpKernel.php:151, Symfony\Component\HttpKernel\HttpKernel->handleRaw()
HttpKernel.php:68, Symfony\Component\HttpKernel\HttpKernel->handle()
Session.php:57, Drupal\Core\StackMiddleware\Session->handle()
KernelPreHandle.php:47, Drupal\Core\StackMiddleware\KernelPreHandle->handle()
PageCache.php:99, Drupal\page_cache\StackMiddleware\PageCache->pass()
PageCache.php:78, Drupal\page_cache\StackMiddleware\PageCache->handle()
ReverseProxyMiddleware.php:47, Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
NegotiationMiddleware.php:52, Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
StackedHttpKernel.php:23, Stack\StackedHttpKernel->handle()
DrupalKernel.php:669, Drupal\Core\DrupalKernel->handle()
index.php:19, {main}()
miro_dietiker’s picture

Status: Active » Postponed (maintainer needs more info)

The massageFormValues is triggered twice, first during validation in validateForm and if there were no errors during doSubmitForm.

It seems your validation provides inconsistent results, thus i would expect that you have some code in place that modifies data on validation?

Tested this without IEF and the validation checks consistent values.

From the description above i can't seem to understand what the relation to IEF is nor what speciflc violation error was triggered.
So can't help much here.

zaporylie’s picture

Status: Postponed (maintainer needs more info) » Active

Thank you Miro for taking the time to reply to this bug report.

  1. I came to the same conclusion that massageFormValues is triggered twice, first via validateForm and then again via submitForm. I'm still not sure if having a code that sets errors inside the method that we know is invoked during form submission is a right thing? Shouldn't there be at least a condition which skips that fragment if invoked by submitForm?
  2. The steps to reproduce I gave in the issue summary were verified on simplytest.me with no custom code whatsoever and with only IEF and Paragraphs contrib modules enabled.
  3. The IEF module in this scenario is used to create a media entity on the fly. And the violation comes from IEF powered field - media reference field. The violation is "This value should not be null." and it is added on field_media.0 property path. I've set the breakpoint in ValidReferenceConstraintValidator to see in what circumstances the violation is added and it is when the entity was already created (Media::save()) but target_id is not set (null). Please note that this situation doesn't happen when the paragraph is not collapsed or when using another Paragraphs widget. It is reproducible only for the EXPERIMENTAL widget.

Please let me know if this is clear now and what additional information you need in order to reproduce the issue.

I believe the core issue here is errors being set (via $form_state->setError()) in submit part of the form submission. Once commented out media submission via IEF works like a charm.

zaporylie’s picture

Status: Active » Needs review
StatusFileSize
new883 bytes

So, as suggested earlier, I think Paragraph validation shouldn't be triggered once the form was already validated. I think that adding a simple check would solve the major issue here.

azinck’s picture

Patch works well for us.

dennis cohn’s picture

I'm using Drupal 8.7.0-alpha1 and the error below is still there after applying #5

LogicException: Form errors cannot be set after form validation has finished. in Drupal\Core\Form\FormState->setErrorByName() (line 1057 of /Users/denniscohn/Sites/flean/web/core/lib/Drupal/Core/Form/FormState.php).

vood002’s picture

I'm using Drupal 8.7.0-beta2 and tried applying this patch to Paragraphs 1.8 and 1.x-dev and in both cases I continued seeing the same error,

LogicException: Form errors cannot be set after form validation has finished. in Drupal\Core\Form\FormState->setErrorByName() (line 1057 of /app/web/core/lib/Drupal/Core/Form/FormState.php).

It's obviously a very simple and concise patch....any other thoughts what might be going on here?

miro_dietiker’s picture

Status: Needs review » Needs work
miro_dietiker’s picture

Issue tags: +Needs tests

Also please help to extend our tests to cover this use case.

zaporylie’s picture

@Dennis Cohn and @vood002 - could you share:
- which fields are you using to trigger this error - is it IEF and Media?
- which field widget for Paragraphs module is in use - Classic or Experimental?
- backtrace when the error occurs? Is it caused by calling `setError` in `massageFormValues`?

niklan’s picture

Having same issue since 8.7.0.

I have paragraph type "image_single" which has entity reference field "field_media_image" . I use "Media Library" widget and this error happens when I click "Added media". For paragraph field I use EXPERIMENTAL widget. There is not nested paragraphs, to be sure. Since it looks like this issue #3003150: Media library causes validation errors when it is used in a required field of a nested form, but patch from that issue is not helps with this problem and patch from #3013171-5: LogicException Form errors cannot be set after form validation has finished also not fix the problem.

UPD With "Paragraphs Classic" field widget media select dialog is opens, but when select value, it "saves" without any values and errors.

My error trace is

LogicException: Form errors cannot be set after form validation has finished. in Drupal\Core\Form\FormState-&gt;setErrorByName() (line 1057 of core/lib/Drupal/Core/Form/FormState.php). Drupal\Core\Form\FormState-&gt;setError(Array, Object) (Line: 466)
Drupal\Core\Field\WidgetBase-&gt;flagErrors(Object, Object, Array, Object) (Line: 264)
Drupal\Core\Entity\Entity\EntityFormDisplay-&gt;flagWidgetsErrorsFromViolations(Object, Array, Object) (Line: 251)
Drupal\Core\Entity\Entity\EntityFormDisplay-&gt;validateFormValues(Object, Array, Object) (Line: 2231)
Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget-&gt;massageFormValues(Array, Array, Object) (Line: 381)
Drupal\Core\Field\WidgetBase-&gt;extractFormValues(Object, Array, Object) (Line: 2284)
Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget-&gt;extractFormValues(Object, Array, Object) (Line: 231)
Drupal\Core\Entity\Entity\EntityFormDisplay-&gt;extractFormValues(Object, Array, Object) (Line: 338)
Drupal\Core\Entity\ContentEntityForm-&gt;copyFormValuesToEntity(Object, Array, Object) (Line: 304)
Drupal\Core\Entity\EntityForm-&gt;buildEntity(Array, Object) (Line: 159)
Drupal\Core\Entity\ContentEntityForm-&gt;buildEntity(Array, Object) (Line: 289)
Drupal\Core\Entity\EntityForm-&gt;submitForm(Array, Object) (Line: 149)
Drupal\Core\Entity\ContentEntityForm-&gt;submitForm(Array, Object)
call_user_func_array(Array, Array) (Line: 111)
Drupal\Core\Form\FormSubmitter-&gt;executeSubmitHandlers(Array, Object) (Line: 51)
Drupal\Core\Form\FormSubmitter-&gt;doSubmitForm(Array, Object) (Line: 590)
Drupal\Core\Form\FormBuilder-&gt;processForm(&#039;node_blog_entry_edit_form&#039;, Array, Object) (Line: 319)
Drupal\Core\Form\FormBuilder-&gt;buildForm(&#039;node_blog_entry_edit_form&#039;, Object) (Line: 93)
Drupal\Core\Controller\FormController-&gt;getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;Drupal\Core\EventSubscriber\{closure}() (Line: 582)
Drupal\Core\Render\Renderer-&gt;executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-&gt;Drupal\Core\EventSubscriber\{closure}() (Line: 151)
Symfony\Component\HttpKernel\HttpKernel-&gt;handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel-&gt;handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session-&gt;handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle-&gt;handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache-&gt;pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache-&gt;handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware-&gt;handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware-&gt;handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel-&gt;handle(Object, 1, 1) (Line: 693)
Drupal\Core\DrupalKernel-&gt;handle(Object) (Line: 19)
mheip’s picture

StatusFileSize
new1.39 KB

I was also getting this issue with Drupal 8.7 and paragraphs 1.8. My LogicException triggered in the if statement above:

if ($widget_state['paragraphs'][$item['_original_delta']]['mode'] === 'edit') {
  $display->validateFormValues($paragraphs_entity, $element[$item['_original_delta']]['subform'], $form_state);
}

Changing this to:

if (!$form_state->isValidationComplete() && $widget_state['paragraphs'][$item['_original_delta']]['mode'] === 'edit') {
  $display->validateFormValues($paragraphs_entity, $element[$item['_original_delta']]['subform'], $form_state);
}

In combo with the patch in #5 resolved it for me.
I have attached my patch.

niklan’s picture

Patch #13 is solved my problem, where #5 can't.

ainarend’s picture

I can confirm that the patch #13 fixed the bug of media library not opening when using Paragraphs with referenced media field and experimental widget.

ainarend’s picture

Status: Needs work » Needs review

Oh and since there is a patch, updating the issue status.

miro_dietiker’s picture

A quick hint: While we have seen multiple runs of validations eating time (and like here resulting in errors), we also have seen cases where nested structures skip validation completely because somehow it was partially skipped but on some level marked as validated (maybe also collapsing related). Some operations (for instance the new convert patch) can produce temporary illegal situations within the UI. We need to make sure that items are guaranteed to be validated before saving.

We definitively need to check the quality of our validation tests combined with nesting, collapsing and maybe more of the complex operations.

ainarend’s picture

Status: Needs review » Needs work

Turns out that the patch from #13 somehow brakes JSON:API responses when using included paragraphs fields in the jsonapi request. Didn't have time to debug why.

So it did fix the media library not working, but caused a regression for jsonapi.
Unrelated bug with config.

And it seems that miro_dietiker also hints that there's more work to be done with this issue.

FNGR’s picture

#13 worked for me too.

br0ken’s picture

Version: 8.x-1.5 » 8.x-1.x-dev

The root problem here is that the method is called at least twice and after the first execution the form is already validated. Suppressing the validation doesn't seem to be a good fix (but as a quick fix it works perfectly fine).

carma03’s picture

+1. Confirmed, #13 worked for me on Drupal 8.7.1 and PHP 7.3. Thanks!

dani3lr0se’s picture

RTBC +1. The patch in #13 worked for me as well. Patch applied cleanly and solved my issue. Using core 8.7.5 and module 8.x-1.8. Thanks!

mbovan’s picture

I tested #13 with a large number of paragraphs (Paragraphs Performance module in combination with latest Drupal core, latest development branch of Paragraphs and ERR modules) where I get on average ~20% (~0.5s difference) faster save times with the patch compared to results without the patch.

berdir’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs tests

I think the issues in #17 aren't really related to this MR and aren't blocking it.

The bugs are non-trivial to test for, and at least the one in media_library is also being fixed in core, so wouldn't help us much then to test I think.

This does have considerable performance improvements, passes our existing tests, we also tested it with our distribution extensively and there were also several reports from others that it is fixing their problems. RTBC.

  • miro_dietiker committed 91a5090 on 8.x-1.x authored by mheip
    Issue #3013171 by zaporylie, mheip, miro_dietiker, ainarend, Niklan,...
miro_dietiker’s picture

Status: Reviewed & tested by the community » Fixed

Yay then, committed. :-) and attributed all, thx!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.