Avoid passing null from $entity->label() when no label key is defined in EntityListBuilder

Created on 10 October 2025, about 1 month ago
Updated 11 October 2025, about 1 month ago

Problem/Motivation

Follow-up from Add 'View' to operations links where available Active
The recent changes in EntityListBuilder https://git.drupalcode.org/project/drupal/-/commit/5cbac86546d697154f1ee... introduced a call to $entity->label() that was not checked for nulls.

This $entity->label() call is returning null from \Drupal\Core\Entity\ContentEntityBase::label() when there is no label key. Previously further down it was checked for if (!empty($entity->label())) {, it's still there as

$label = $entity->label()
        ? $this->t('Edit @entity_label', $variables)
        : $this->t('Edit @entity_bundle @entity_id', $variables);

But this one is causing some grief in og contrib module. See 🐛 Fix PHPUnit next minor test in pipeline Active

Steps to reproduce

1. Define a custom content entity type that does not set a label key.
2. Go to a menu tab that tries to get a label on the entity type
3. Fail.

TypeError: Drupal\Component\Utility\Html::escape(): Argument #1 ($text) must be of type string, null given, called in /var/www/html/web/core/lib/Drupal/Component/Render/FormattableMarkup.php on line 238 in Drupal\Component\Utility\Html::escape() (line 433 of core/lib/Drupal/Component/Utility/Html.php).

Drupal\Component\Render\FormattableMarkup::placeholderEscape() (Line: 187)
Drupal\Component\Render\FormattableMarkup::placeholderFormat() (Line: 195)
Drupal\Core\StringTranslation\TranslatableMarkup->render() (Line: 15)
Drupal\Core\StringTranslation\TranslatableMarkup->__toString() (Line: 22)
Drupal\Component\Render\PlainTextOutput::renderFromHtml() (Line: 152)
Drupal\Core\Template\Attribute->createAttributeValue() (Line: 112)
Drupal\Core\Template\Attribute->offsetSet() (Line: 87)
Drupal\Core\Template\Attribute->__construct() (Line: 201)
Drupal\Core\Utility\LinkGenerator->doGenerate() (Line: 181)
Drupal\Core\Utility\LinkGenerator->generate() (Line: 104)
Drupal\Core\Render\Element\Link::preRenderLink()
call_user_func_array() (Line: 107)
Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 908)
Drupal\Core\Render\Renderer->doCallback() (Line: 440)
Drupal\Core\Render\Renderer->doRender() (Line: 229)
Drupal\Core\Render\Renderer->render() (Line: 501)
Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 82)
__TwigTemplate_0abd1b0ced69e52dd2ed63ed9632a88e->doDisplay() (Line: 402)
Twig\Template->yield() (Line: 386)
Twig\Template->render() (Line: 51)
Twig\TemplateWrapper->render() (Line: 34)
twig_render_template() (Line: 416)
Drupal\Core\Theme\ThemeManager->render() (Line: 499)
Drupal\Core\Render\Renderer->doRender() (Line: 229)
Drupal\Core\Render\Renderer->render() (Line: 1215)
Drupal\views\Plugin\views\field\FieldPluginBase->advancedRender() (Line: 451)
Drupal\views\Hook\ViewsThemeHooks->preprocessViewsViewField() (Line: 293)
Drupal\Core\Theme\ThemeManager->render() (Line: 499)
Drupal\Core\Render\Renderer->doRender() (Line: 229)
Drupal\Core\Render\Renderer->render() (Line: 1811)
Drupal\views\Plugin\views\field\FieldPluginBase->theme() (Line: 778)
Drupal\views\Plugin\views\style\StylePluginBase->elementPreRenderRow()
call_user_func_array() (Line: 107)
Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 908)
Drupal\Core\Render\Renderer->doCallback() (Line: 440)
Drupal\Core\Render\Renderer->doRender() (Line: 229)
Drupal\Core\Render\Renderer->render() (Line: 715)
Drupal\views\Plugin\views\style\StylePluginBase->renderFields() (Line: 579)
Drupal\views\Plugin\views\style\StylePluginBase->renderGrouping() (Line: 467)
Drupal\views\Plugin\views\style\StylePluginBase->render() (Line: 2213)
Drupal\views\Plugin\views\display\DisplayPluginBase->render() (Line: 1595)
Drupal\views\ViewExecutable->render() (Line: 70)
Drupal\views\Plugin\views\display\DefaultDisplay->execute() (Line: 1692)
Drupal\views\ViewExecutable->executeDisplay() (Line: 37)
Drupal\og\Controller\OgAdminMembersController->membersList()
call_user_func_array() (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->{closure:Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber::wrapControllerExecutionInRenderContext():121}() (Line: 633)
Drupal\Core\Render\Renderer::{closure:Drupal\Core\Render\Renderer::executeInRenderContext():633}()
Fiber->resume() (Line: 647)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 121)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->{closure:Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber::onController():96}() (Line: 183)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 118)
Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 92)
Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 53)
Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 54)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 716)
Drupal\Core\DrupalKernel->handle() (Line: 19)

Proposed resolution

Make the result a string.
MR coming

🐛 Bug report
Status

RTBC

Version

11.0 🔥

Component

entity system

Created by

🇨🇦Canada joelpittet Vancouver

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.

No activities found.

Production build 0.71.5 2024