Problem/Motivation
When submitting an entityreference field setting that is marked as required, a fatal error occurs (see below).
Steps to reproduce
- Fresh D8 installation (minimal profile)
- Enabled Field UI
- Added new node type "story"
- Added a new EntityReference Field "field_story_ref" (Content Types: Story, Required: unchecked) => No Error
- Editing field_story_ref without changing any field setting => No Error
- Editing field_story_ref with Required checked => No Error
- Editing field_story_ref with Required still checked => Error occurs (see below)
- Editing field_story_ref with Required unchecked => Error occurs too (see below)


Error Message 1
Notice: Undefined index: target_id in Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase->errorElement() (line 108 of /WEBSITES/undpaul/undsyncer/pages/undsyncer/drupal/core/modules/entity_reference/src/Plugin/Field/FieldWidget/AutocompleteWidgetBase.php).
Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase->errorElement(Array, Object, Array, Object)
Drupal\Core\Field\WidgetBase->flagErrors(Object, Object, Array, Object)
Drupal\Core\Field\FieldItemList->defaultValuesFormValidate(Array, Array, Object)
Drupal\field_ui\Form\FieldEditForm->validateForm(Array, Object)
call_user_func_array(Array, Array)
Drupal\Core\Form\FormValidator->executeValidateHandlers(Array, Object)
Drupal\Core\Form\FormValidator->doValidateForm(Array, Object, 'field_ui_field_edit_form')
Drupal\Core\Form\FormValidator->validateForm('field_ui_field_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->processForm('field_ui_field_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object)
Drupal\Core\Controller\FormController->getContentResult(Object)
call_user_func_array(Array, Array)
Drupal\Core\Controller\HtmlPageController->getContentResult(Object, Array)
Drupal\Core\Controller\HtmlPageController->content(Object, Array)
call_user_func_array(Array, Array)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\PageCache->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1)
Stack\StackedHttpKernel->handle(Object, 1, 1)
Drupal\Core\DrupalKernel->handle(Object)
Recoverable fatal error: Argument 1 passed to Drupal\Core\Form\FormState::setError() must be of the type array, null given, called in /WEBSITES/undpaul/undsyncer/pages/undsyncer/drupal/core/lib/Drupal/Core/Field/WidgetBase.php on line 431 and defined in Drupal\Core\Form\FormState->setError() (line 1056 of /WEBSITES/undpaul/undsyncer/pages/undsyncer/drupal/core/lib/Drupal/Core/Form/FormState.php).
Drupal\Core\Form\FormState->setError(NULL, 'This value should not be null.')
Drupal\Core\Field\WidgetBase->flagErrors(Object, Object, Array, Object)
Drupal\Core\Field\FieldItemList->defaultValuesFormValidate(Array, Array, Object)
Drupal\field_ui\Form\FieldEditForm->validateForm(Array, Object)
call_user_func_array(Array, Array)
Drupal\Core\Form\FormValidator->executeValidateHandlers(Array, Object)
Drupal\Core\Form\FormValidator->doValidateForm(Array, Object, 'field_ui_field_edit_form')
Drupal\Core\Form\FormValidator->validateForm('field_ui_field_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->processForm('field_ui_field_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object)
Drupal\Core\Controller\FormController->getContentResult(Object)
call_user_func_array(Array, Array)
Drupal\Core\Controller\HtmlPageController->getContentResult(Object, Array)
Drupal\Core\Controller\HtmlPageController->content(Object, Array)
call_user_func_array(Array, Array)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\PageCache->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1)
Stack\StackedHttpKernel->handle(Object, 1, 1)
Drupal\Core\DrupalKernel->handle(Object)
Follow Up
After doing a quick workaround (I guess this might not be the real solution) to avoid the fatal error in \Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase::errorElement():
public function errorElement(array $element, ConstraintViolationInterface $error, array $form, FormStateInterface $form_state) {
return $element;
}
the validation error "This value should not be null." occures.

I'm currently not sure whether we should handle that as a separate issue or it tightly belongs to the fatal error.
Proposed resolution
Select the correct element in \Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase::errorElement() for assigning the error.
Remaining tasks
- Fixing \Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase::errorElement()
- Fixing the required field setting default value problem for the Autocomplete widget in this or a separate issue
Contributor tasks needed
| Task |
Novice task? |
Contributor instructions |
Complete? |
| Manually test the patch |
Novice |
Instructions |
|
| Investigate to confirm whether the problem applies to all fields |
Novice |
|
|
| Add automated tests (See #10) |
|
Instructions |
|
User interface changes
API changes
Comments
Comment #1
tstoecklerHere's a test proving that this is broken.
Upgrading to critical, because this is a Fatal you can trigger from the UI and adding a required Entity reference field is not really an edge case.
Comment #3
tstoecklerComment #4
tstoecklerThis implements the solution from the issue summary. Since
WidgetBasealready has anerrorElement()method which just returns$elementI removed the entire method.We might want to commit this as is, it's certainly an improvement over the status quo and the fix is correct.
The problem mentioned in the issue summary remains, however.
Comment #5
amateescu commentedNope, there's nothing wrong with
\Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase::errorElement(), this bug is a bit more subtle than that.The problem here is that
\Drupal\Core\Field\FieldItemList::defaultValuesFormValidate()calls thevalidate()method on itself but it does not account for the fact that, when dealing with the default value form / widget, the field definition should *not* be required. See the code that does this for the widget form itself in\Drupal\Core\Field\FieldItemList::defaultValueWidget().Here's the correct fix :)
Comment #6
amateescu commentedAlso fixed a comment.
Comment #7
spadxiii commentedI just ran into this issue myself as well. It also fixes the problem that you can't switch the reference method for a required field. (The ajax-request generates the error about the target_id as well)
After applying this patch (to d8 beta2), these problems were gone!
Comment #8
tstoecklerHmm... #4 fixes a separate bug so is legit as well IMO.
Comment #9
amateescu commented@tstoeckler, I don't see what bug is being fixed by #4.
Field widgets that do not return the $element they receive in
formElement()and wrap it in another array, have to implementerrorElement()to let the system know about their wrapper. SeePathWidgetandNumberWidgetfor other examples and the docblock ofWidgetInterface::errorElement().Comment #10
alexpottThis affects all fields - right? Seems strange to bury the test for this in EntityReferenceAdminTest - I would have expected a test in ManageFieldsTest.
Comment #11
tstoecklerRe #9: The thing is that AutocompleteWidgetBase does not define a 'target_id' sub-element. That's why the current implementation of errorElement() is wrong. It is proven by the "undefined index" error in the IS and in #1.
Comment #12
amateescu commentedOhboy...
Comment #13
amateescu commented@tstoeckler, are we looking at the same code here? :)
http://cgit.drupalcode.org/drupal/tree/core/modules/entity_reference/src...
Comment #14
tstoecklerHmm... you're right. Sorry about that. Still patch #1 proves that this is "valid" with some definition of valid. I'll have to debug that in detail. But in that case let's proceed here. Sorry for holding this up.
Comment #15
yesct commentedadding needs issue summary update, because I'm not sure if the items in the remaining tasks still need to be done, or if there needs to be a separate issue opened.
If this is going to be used for the Friday Critical Office Hours, then we need to be more clear here.
Comment #16
amateescu commentedHeh, I was wondering earlier today what happened to this issue.
IMO, both the proposed resolution and the remaining tasks from the current issue summary are inaccurate because there's nothing wrong with
\Drupal\entity_reference\Plugin\Field\FieldWidget\AutocompleteWidgetBase::errorElement(), as proven by the patch in #6.The only thing needed here in addition to #6 is a test in ManageFieldsTest that checks the ->required property of the field definition to be always FALSE, regardless of the actual (stored) field definition.
Comment #17
swentel commentedI've quickly checked to start a test in managefields in testDefaultValue(). However, it wasn't possible to get this fail on test_field.
So I'm starting to doubt this is indeed the right fix and starting to slowly agree with @tstoeckler that the problem lies in AutocompleteWidgetBase()/AutocompleteWidget.
Comment #18
amateescu commentedHere you go :) Apparently it only happens when the field has unlimited cardinality.
Comment #19
swentel commentedOh wow, never thought about that .. ok looks fine to me.
Also tagging.
Comment #20
swentel commentedActually, shouldn't we use format_string here ?
Comment #21
swentel commentedSo we don't do it either in the same test. Could potentially be a novice follow up to change those, but shouldn't hold up this patch.
Comment #23
swentel commentedGood to go
Comment #24
alexpottThis issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 01d9799 and pushed to 8.0.x. Thanks!