Problem/Motivation

Submitting a configuration form crashes, if inline_form_errors is enabled, at least one configuration value of the form are overridden and there are invalid items in the configuration related to the form.

Steps to reproduce

  1. Export the current configuration.
  2. Add the following line to system.performance.yml of the configuration export:
    invalid_conf: 12345
  3. Import the altered configuration.
  4. Add the following line to settings.php:
    $config['system.performance']['css']['preprocess'] = FALSE;
  5. Visit /admin/config/development/performance. The page should show the message that values of the form are overridden and will be saved, but will not apply.
  6. Save the form. There should be an error message about "invalid_conf" being an invalid key.
  7. Install inline_form_errors.
  8. Save the form at /admin/config/development/performance again. Now the site crashes with this error message:
    Got error 'PHP message: Uncaught PHP Exception TypeError: "implode(): If argument #1 ($separator) is of type string, argument #2 ($array) must be of type array, null given" at .../web/core/lib/Drupal/Core/Form/FormElementHelper.php line 28',

Proposed resolution

In inline_form_errors/src/FormErrorHandler.php in displayErrorMessages() FormElementHelper::getElementByName($name, $form) is called which has this code:

public static function getElementByName($name, array $form) {
  foreach (Element::children($form) as $key) {
    if (implode('][', $form[$key]['#parents']) === $name) {
      [...]
    }
    [...]
  }
  return [];
}

Since there is a config override, $form contains the key "config_override_status_messages", but $form['config_override_status_messages']['#parents'] does not exist.

Now, I'm not sure how to fix this. The obvious fix would be to check in FormElementHelper::getElementByName() if $form[$key]['#parents'] exists, before using it. However, if I understand correctly, there is an invariant, that $form[$key]['#parents'] should exist.

"config_override_status_messages" is inserted into the form via ConfigFormBase::checkConfigOverrides(), which is called from FormBuilder::doBuildForm() via "#after_build". "#parents" is added to elements of the form earlier, also in FormBuilder::doBuildForm(). So it seems, that doBuildForm() is never run on "config_override_status_messages" and therefore "#parents" is missing. Now, should "#parents" be added via ConfigFormBase::checkConfigOverrides() or should it be arranged somehow that doBuildForm() is run on "config_override_status_messages"?

Remaining tasks

User interface changes

None.

Introduced terminology

None.

API changes

None.

Data model changes

None.

Release notes snippet

Comments

lukas_w created an issue.