Problem/Motivation

In \Drupal\Core\Render\Element::children(), while looping through the elements in the render array, there's an if/elseif statement which reads as follows (I've put line numbers at the start which reflect the state of the file at commit a19a3806e2, the HEAD of 8.8.x at time-of-writing)

81: if ($key === '' || $key[0] !== '#') {
82:  if (is_array($value)) {
        // ...
93:  }
94:  // Only trigger an error if the value is not null.
95:  // @see https://www.drupal.org/node/1283892
96:  elseif (isset($value)) {
97:    trigger_error(new FormattableMarkup('"@key" is an invalid render array key', ['@key' => $key]), E_USER_ERROR);
98:  }
99: }

The error message triggered on line 97 is misleading: it is being triggered because $value is set (line 96) but is not an array (line 82)... and in fact, $key is perfectly valid because of the check on line 81.

I was running into this error on a client site inherited from another vendor when a Drupal theme twig file included a Patternlab twig file (which involved some sort of custom patternlab/drupal integration), because at the time this piece of code ran, my array looked like...

[
  // ...
  'sidebar_resource_download_text' => new TranslatableMarkup('Download this resource'),
  // ...
]

... so the check on line 81 passed ($key was not empty and did not start with a number-sign), the check on line 82 failed (a TranslatableMarkup object is not an array), and the elseif on line 96 passed ($value was set), so an error was triggered. That is to say, $key was valid, but $value was not. The message, 'User error: "sidebar_resource_download_text" is an invalid render array key'... was really confusing and sent me down the wrong debugging path for a while until I stepped through the loop in a debugger, and found the key was fine; it was the value that was wrong.

Speculating, it looks like that trigger_error was supposed to go with the outer if statement; but, probably due to a merge conflict, got attached to the inner if statement.

Proposed resolution

  1. Move the elseif (isset($value)) { trigger_error(...); } to the outer if statement
  2. Optional: add an else { trigger_error(...('Expected an array but got a @type', ['@type' => gettype($value)]), E_USER_ERROR); } to the inner if statement

Remaining tasks

  1. Write a patch
  2. Review
  3. RTBC
  4. Determine if we need a release notes snippet, and if so, write one.
  5. Commit

User interface changes

No UI changes.

API changes

No API changes.

Data model changes

No data model changes.

Release notes snippet

To be done.

Issue fork drupal-3083690

Command icon 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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mparker17 created an issue. See original summary.

mparker17’s picture

Okay, here's a patch that both moves the check, and adds the optional "expected an array but got @type" error.

mparker17’s picture

Status: Active » Needs review

This patch Needs Review.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Kris77’s picture

@mparker17 after apply your patch(with drupal 8.9.8) the site slow down and receive this error:

User error: "#theme" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).
User error: "#message_list" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).
User error: "#status_headings" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).
User error: "#cache" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).
User error: "#lazy_builder_built" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).
User error: "#attached" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).
User error: "#cache" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).
User error: "#attached" is an invalid render array key in Drupal\Core\Render\Element::children() (line 103 of core/lib/Drupal/Core/Render/Element.php).

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

klonos’s picture

I tried to backport this to Backdrop, and confirm @Kris77's findings. I got a series (dozens) of errors of this type:

User error: [#some_element_property] is an invalid render array key. in element_children() (line 7390 of /app/docroot/core/includes/common.inc).

klonos’s picture

Status: Needs review » Needs work
jungle’s picture

FileSize
735 bytes

Maybe it's fine just to ignore invalid keys.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

joachim’s picture

Issue tags: +Novice

I don't think patch #12 is right. We shouldn't be ignoring invalid keys -- if there is an invalid key, then the developer has made a mistake in the output of their render array, and they need to be told so they can fix it.

The first part of patch #2 looks nearly right. The second part doesn't seem relevant to me -- I don't know when that condition would fire, but it's out of scope for this issue.

One other tweak -- the isset() should be kept, otherwise we'll be adding new errors for NULL values. (And perhaps we *should* do that -- but again, that is out of scope).

Tagging as novice:

- update patch #2
- remove the 2nd chunk
- preserve the isset() condition
- make an MR

gxleano made their first commit to this issue’s fork.

gxleano’s picture

Status: Needs work » Needs review
joachim’s picture

Status: Needs review » Needs work

Thanks for the MR. The @key needs to be preserved so the developer knows where the problem is.

gxleano’s picture

Status: Needs work » Needs review
gxleano’s picture

Thanks @joachim to put an eye on it.

I've put back the @key and also updated the tests that go with it.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs Review Queue Initiative

Ran the test-only feature and got

1) Drupal\Tests\Core\Render\ElementTest::testInvalidChildren
Failed asserting that exception message '"foo" is an invalid render array key' contains '"foo" is an invalid render array key. Value should be an array but got a string'.
/builds/issue/drupal-3083690/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:121
/builds/issue/drupal-3083690/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:55
/builds/issue/drupal-3083690/vendor/phpunit/phpunit/src/Framework/TestResult.php:728
/builds/issue/drupal-3083690/vendor/phpunit/phpunit/src/Framework/TestSuite.php:684
/builds/issue/drupal-3083690/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:651
/builds/issue/drupal-3083690/vendor/phpunit/phpunit/src/TextUI/Command.php:144
/builds/issue/drupal-3083690/vendor/phpunit/phpunit/src/TextUI/Command.php:97
FAILURES!
Tests: 38, Assertions: 51, Failures: 1.

So change has coverage. Think this is a nice little improvement

alexpott’s picture

Version: 11.x-dev » 10.3.x-dev
Category: Feature request » Task
Status: Reviewed & tested by the community » Fixed

Committed and pushed ee4eaba6ff to 11.x and 85d08d1cfb to 10.3.x. Thanks!

Can we get a follow-up to convert the 3 core instances of trigger_error(new FormattableMarkup( to trigger_error(sprintf( - we should not using FormattableMarkup here.

  • alexpott committed 85d08d1c on 10.3.x
    Issue #3083690 by gxleano, mparker17, jungle, joachim, Kris77: '"@key"...

  • alexpott committed ee4eaba6 on 11.x
    Issue #3083690 by gxleano, mparker17, jungle, joachim, Kris77: '"@key"...
joachim’s picture

Yup, I spotted that but it was out of scope to change that here.

There is #2552163: Do not use FormattableMarkup in exceptions, trigger_error, and debug (the second pass).

Status: Fixed » Closed (fixed)

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