Fatal error on multiple rendering of already printed block with empty markup

Created on 6 October 2017, about 7 years ago
Updated 1 September 2024, 4 months ago

Problem/Motivation

Within a templateregion--header.html.twig we render a block "manually" by calling " a custom block via {{ elements.my_project_block_plugin_1 }}. This leads to a fatal error in case the custom block plugin returns an empty markup string

  public function build() {
    // [...]
    return [
      '#markup' => '',
    ];
  }

:

Error: Call to a member function getPlugin() on null in Drupal\block\BlockViewBuilder::preRender() (line 203 of core/modules/block/src/BlockViewBuilder.php).

It appears that some circumstances lead to the block being rendered a second time, although it has been rendered before and has been marked as #printed already:

  1. Region "header" is rendered in page.html.twig as {{ page.header }}.
  2. This leads to all children being render processed and concatenated to #children beforehand.
  3. As the region template itself renders the child directly via {{ elements.my_project_block_plugin_1 }}, the block is passed to \Drupal\Core\Template\TwigExtension::escapeFilter() once again.
  4. There the check on the element being already renders fails, as it also checks on strlen($arg['#markup']) > 0.
  5. This leads to the re-rendering of the block - at least the try of it.

From my perspective this seems like a generic bug, as this may lead to multiple render processing of elements that simply will fall back to an empty string.

Proposed resolution

* Remove the general check on strlen($arg['#markup']) in

// Early return if this element was pre-rendered (no need to re-render).
if (isset($arg['#printed']) && $arg['#printed'] == TRUE && isset($arg['#markup']) && strlen($arg['#markup']) > 0) {
   return $arg['#markup'];
}

appearing in \Drupal\Core\Template\TwigExtension::escapeFilter() and \Drupal\Core\Template\TwigExtension::renderVar()

Remaining tasks

* Write a test.
* Clarify what the intensions were in #2464045: Move twig_render_var/twig_drupal_escape_filter to TwigExtension, inject the renderer in Twig extension and inline render() / show() function instead of calling it β†’ of adding strlen($arg['#markup']).
* Fix

User interface changes

-

API changes

-

Data model changes

-

πŸ› Bug report
Status

Closed: outdated

Version

11.0 πŸ”₯

Component
RenderΒ  β†’

Last updated about 9 hours ago

Created by

πŸ‡©πŸ‡ͺGermany derhasi

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡¦πŸ‡ΊAustralia acbramley

    Just on 6 years with no futher comments, is this still an issue?

    The strlen check still exists in 11.x, and the description in the IS is a bit confusing, specifically:

    This leads to the re-rendering of the block - at least the try of it.

    But the code comments state the opposite - i.e it's trying to prevent re-rendering.

    If the problem still exists, please provide steps to reproduce from a fresh installation of Drupal core.

    Thanks!

  • Status changed to Closed: outdated 4 months ago
  • πŸ‡³πŸ‡ΏNew Zealand quietone

    More information about this issue was asked for in #7, just about 1 year ago. No additional information has been supplied, therefor closing.

    If you are experiencing this problem on a supported version of Drupal reopen the issue, by setting the status to 'Active', and provide complete steps to reproduce the issue β†’ (starting from "Install Drupal core").

    Thanks!

Production build 0.71.5 2024