Project version
- DXPR Builder 2.8.0
- Also reproducible in 2.8.1-beta1
- Drupal 11.3.x
- PHP 8.3
### Problem/Motivation
Drupal\dxpr_builder\Service\Handler\ViewHandler::getView() assumes that ViewExecutable::render() always returns a render array:
$rendered_view = $view->render($displayId);
$output = $this->renderer->render($rendered_view);
However, ViewExecutable::render() is documented to return array|null. It returns NULL when the View build fails or access is denied, including cases such as:
- Contextual argument validation failures.
- A missing default contextual argument on routes without a current node.
- A View display whose build sets build_info['fail'].
- A View display whose build sets build_info['denied'].
DXPR Builder then passes that NULL value to Renderer::render().
Drupal 11.3 emits the following deprecation warning:
Calling Drupal\Core\Render\Renderer::render with NULL is deprecated in
drupal:11.3.0 and is removed from drupal:12.0.0. Either pass an array or
skip the call. See https://www.drupal.org/node/3534020.
This can produce a large number of log entries when a DXPR View element is included in a global block, such as a footer, and the View cannot resolve its contextual argument on login, 403, 404, or other non-node routes.
In Drupal 12, RendererInterface::render() will require an array, so this will become a compatibility error rather than only a deprecation warning.
### Steps to reproduce
1. Install Drupal 11.3.x and DXPR Builder 2.8.x.
2. Create a View with a contextual argument whose default value depends on the current node.
3. Add the View to a DXPR CMS View element.
4. Render the element on a route without a current node, or supply an invalid contextual argument that fails validation.
5. Check the Drupal logs.
### Actual result
The View returns NULL, and DXPR Builder calls:
$this->renderer->render(NULL);
Example stack trace:
Drupal\Core\Render\Renderer->render()
Drupal\dxpr_builder\Service\Handler\ViewHandler->getView()
Drupal\dxpr_builder\Service\DxprBuilderService->loadCmsElement()
Drupal\dxpr_builder\Service\DxprBuilderService->parseDocumentForCmsElements()
Drupal\dxpr_builder\Service\DxprBuilderService->parseForContent()
Drupal\dxpr_builder\Service\DxprBuilderService->updateHtml()
Drupal\dxpr_builder\Plugin\Field\FieldFormatter\DxprBuilderFormatter->viewElements()
### Expected result
DXPR Builder should detect the documented NULL return value and skip the renderer call.
The existing ViewHandlerInterface already permits a boolean return value, and DxprBuilderService::loadCmsElement() already handles falsey output by rendering an empty CMS element placeholder.
### Proposed resolution
Add a strict NULL guard before calling the renderer:
$rendered_view = $view->render($displayId);
if ($rendered_view === NULL) {
return FALSE;
}
$output = $this->renderer->render($rendered_view);
A strict comparison is preferable because an empty render array is valid and should continue through the normal rendering path.
### Remaining tasks
- Add the NULL guard to ViewHandler::getView().
- Add regression coverage for a View whose build fails.
- Confirm that attached libraries and drupalSettings continue to work for successful View renders.
- Confirm Drupal 12 compatibility.
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | 3618203-2-skip-renderer-when-view-returns-null.patch | 1.34 KB | drale01 |
Comments
Comment #2
drale01 commentedWe reproduced this on Drupal 11.4 with DXPR Builder 2.8.0 and confirmed the same bug is still present on the 3.x branch.
A GitHub issue and pull request are opened. The attached patch is for the 2.8.x line so sites can apply it with composer-patches until a release includes the fix.
The patch skips Renderer::render() when ViewExecutable::render() returns NULL and returns FALSE instead. loadCmsElement() already turns that into the empty CMS placeholder. An empty render array still goes through the normal renderer.
Comment #3
freddy rodriguezHello Drale,
I can confirm that it’s working without any issues.
Thanks
Comment #4
drale01 commented