Problem/Motivation
Drupal\field_ui\Form\EntityDisplayFormBase::copyFormValuesToEntity() assumes that every field listed in $form['#fields'] is also present in $form_values['fields'].
That assumption is not always valid during Field UI multistep/AJAX operations using limited validation. In an intermediate rebuild, FormState may intentionally contain only the values for the component currently being edited.
Core nevertheless iterates over all entries in $form['#fields'] and dereferences the corresponding values unconditionally:
foreach ($form['#fields'] as $field_name) {
$values = $form_values['fields'][$field_name];This results in warnings such as:
Warning: Undefined array key "created" in Drupal\field_ui\Form\EntityDisplayFormBase->copyFormValuesToEntity()
Warning: Trying to access array offset on null in Drupal\field_ui\Form\EntityDisplayFormBase->copyFormValuesToEntity()
The same assumption exists in the loop handling $form['#extra'].
This can be reproduced with Field Group, but the issue is not specific to Field Group. The underlying problem is that copyFormValuesToEntity() does not tolerate a valid partial submitted values tree during multistep Field UI operations.
Steps to reproduce
Tested with Drupal 11.4.8.
- Install and enable Field Group.
- Create a content type.
- Add at least one configurable field, for example a text field.
- Go to Manage form display.
- Click the settings cog for the
Titlebase field. - Observe that the settings form opens without warnings.
- Add a Field Group to the form display.
- Put one or more fields into that group and save.
- Return to Manage form display.
- Click the settings cog for the
Titlefield again.
PHP warnings are emitted from EntityDisplayFormBase::copyFormValuesToEntity().
The issue is especially easy to reproduce with base fields such as title.
Instrumentation in copyFormValuesToEntity() shows multiple calls during the multistep request. A normal/full call contains all fields. However, an intermediate call when opening the Title widget settings contains only title, langcode, status, uid, while $form['#fields'] still contains all the remaining fields. Therefore fields are absent from $form_values['fields'] during that intermediate rebuild, but core then attempts to access them anyway. A later rebuild contains the complete values tree again.
Proposed resolution
Skip display components that are not present in the current submitted values.
For regular fields:
foreach ($form['#fields'] as $field_name) {
if (!isset($form_values['fields'][$field_name])) {
continue;
}
$values = $form_values['fields'][$field_name];
// Existing processing.
}
Apply the same guard to the #extra loop:
foreach ($form['#extra'] as $name) {
if (!isset($form_values['fields'][$name])) {
continue;
}
if ($form_values['fields'][$name]['region'] == 'hidden') {
$entity->removeComponent($name);
}
else {
$entity->setComponent($name, [
'weight' => $form_values['fields'][$name]['weight'],
'region' => $form_values['fields'][$name]['region'],
]);
}
}If a component is absent from the current limited-validation submission, it should be left unchanged. With these guards in place:
- the PHP warnings disappear;
- the base-field widget settings form opens correctly;
- configurable-field widget settings continue to work;
- the later rebuild again contains the full field values tree;
- the form display remains functional.
The change only skips components that were not submitted in the current partial form state.
Remaining tasks
- Add automated test coverage for partial
$form_values['fields']. - Cover both
$form['#fields']and$form['#extra']. - Confirm behavior for Manage form display and Manage display.
- Confirm whether
isset()orarray_key_exists()is preferred. - Add a current merge request against the supported core branch.
Related issues
#3188588: EntityDisplayFormBase (Form Display) throws Notices when opening field settings for Media Library Widget
#3188588 reported the same underlying failure in copyFormValuesToEntity() and proposed essentially the same defensive guard: skip processing when the corresponding field values are absent. That issue was later closed as a duplicate of #3134554.
#3134554: Media fields with Media Library form widget trigger PHP 'Notice: Undefined index'
The root cause in #3134554 was specific to MediaLibraryWidget::settingsForm(), which returned the incoming form instead of only its own settings elements. The accepted resolution was therefore Media Library-specific, rather than adding a general defensive check to EntityDisplayFormBase.
The present issue has a different reproducer and does not require Media Library. Notably, #3188588 also received a later report in 2024 of the same warnings affecting Paragraphs and custom entities, with the reporter confirming that the old defensive patch from #3188588 resolves the issue.
Issue fork drupal-3631593
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
jordik commentedComment #3
jordik commentedComment #4
jordik commentedComment #6
jordik commented[MR !17491] is ready for review.
The regression test fails on unpatched core with PHP warnings and corruption of omitted component configuration, and passes with the proposed guards for regular fields and `#extra` components.
Comment #7
jordik commentedComment #8
quietone commentedIssue are fixed on the development branch first, which is 'main'.