Problem/Motivation
Drupal 11.4 added recursion protection to EntityViewBuilder. Every entity build gets a matched pair of callbacks in EntityViewBuilder::getBuildDefaults():
$build['#pre_render'] = [[$this, 'setRecursiveRenderProtection']]; $build['#post_render'] = [[$this, 'unsetRecursiveRenderProtection']];
LayoutParagraphsBuilder::buildComponent() replaces #post_render instead of appending to it, so core's cleanup callback is dropped:
$build = $view_builder->view($entity, $preview_view_mode, $entity->language()->getId()); $build['#post_render'] = [ [$this, 'postRenderComponent'], ];
Every component the builder renders therefore adds its recursion key to the static tracker and never removes it. The key survives for the rest of the request, and the next render of that same paragraph is aborted as a false positive:
User warning: Recursive rendering attempt aborted for paragraph:entity_id:772:11204:fiber_id:194:en:default. In progress: Array ( ... ) in Drupal\Core\Entity\EntityViewBuilder->setRecursiveRenderProtection() (line 564 of core/lib/Drupal/Core/Entity/EntityViewBuilder.php).
The aborted build gets #printed = TRUE, so that component renders empty.
Rendering the same paragraph twice in one request is ordinary, not a bug. Any theme whose paragraph.html.twig assigns content|render to a variable - a widespread idiom for bubbling the cacheability of fields the template does not print, and for testing whether content is empty - renders every field and every nested component a second time, because Twig resets #printed on each render.
Steps to reproduce
- Drupal 11.4, Layout Paragraphs, a section with at least one child component.
- Add
{% set rendered_content = content|render %}to the top of the theme'sparagraph.html.twig. - Open the host entity's edit form. The nested component renders empty and the warning above is logged.
Proposed resolution
Append the callback rather than replace the array:
$build['#post_render'][] = [$this, 'postRenderComponent'];
Remaining tasks
Review. The same line is in 2.0.x, 2.1.x and 2.2.x and needs the same one-line change.
Issue fork layout_paragraphs-3620623
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 #3
serhii shandaliuk commentedMR !262. One line:
$build['#post_render'][] = [$this, 'postRenderComponent'];instead of replacing the array.Regression test added: a test module whose
paragraph.html.twigrenderscontenttwice, plus a functional test that puts a text component inside a one-column section and loads the host node's edit form. Without the fix the nested component's second render is aborted and the resulting PHP warning fails the test.Verified on Drupal 11.4.5, PHP 8.3, Layout Paragraphs 3.0.x:
phpunit tests/src/Functional/- 2 tests, 25 assertions, OK.phpcs --standard=Drupal,DrupalPractice- clean.phpstan- no errors.Also reproduced and fixed on a live 11.4.5 site running 2.1.3 with Mercury Editor: 12 warnings per page load before, none after.
Comment #4
benstallings commentedThis is a correct, narrowly-scoped fix with a good regression test, and MR!262 matches the resolution proposed in the issue. Nothing to flag as a defect.