Exception thrown on usage page if a layout builder block has usage but its parent entity was deleted

Created on 23 May 2025, 14 days ago

Problem/Motivation

Layout Builder uses "inline blocks" - block content entities that only "exist" within the context of the layout builder entity that contains them. E.g., these blocks are non-reusable and are deleted when the layout builder entity using them is deleted. However, they're not deleted immediately, but instead only when cron runs.

So, there's a period of time where the inline block still exists in the database, but it's parent entity doesn't. In other words, inline blocks are really only "soft deleted" when their parent entity is deleted.

If a soft-deleted inline block is an entity usage source, then the usage report page will throw an exception:

TypeError: Drupal\layout_builder\EventSubscriber\SetInlineBlockDependency::isLayoutCompatibleEntity(): Argument #1 ($entity) must be of type Drupal\Core\Entity\EntityInterface, null given, called in .../docroot/core/modules/layout_builder/src/EventSubscriber/SetInlineBlockDependency.php on line 134 in Drupal\layout_builder\EventSubscriber\SetInlineBlockDependency->isLayoutCompatibleEntity() (line 36 of core/modules/layout_builder/src/LayoutEntityHelperTrait.php).

Drupal\layout_builder\EventSubscriber\SetInlineBlockDependency->getInlineBlockDependency(Object) (Line: 95)
Drupal\layout_builder\EventSubscriber\SetInlineBlockDependency->onGetDependency(Object, 'block_content.get_dependency', Object)
call_user_func(Array, Object, 'block_content.get_dependency', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'block_content.get_dependency') (Line: 92)
Drupal\block_content\BlockContentAccessControlHandler->checkAccess(Object, 'view', Object) (Line: 109)
Drupal\Core\Entity\EntityAccessControlHandler->access(Object, 'view', Object, ) (Line: 739)
Drupal\Core\Entity\ContentEntityBase->access('view label') (Line: 486)
Drupal\entity_usage\Controller\ListUsageController->getSourceEntityLink(Object) (Line: 296)
Drupal\entity_usage\Controller\ListUsageController->getRows('media', '1') (Line: 146)
Drupal\entity_usage\Controller\ListUsageController->listUsagePage('media', '1') (Line: 54)
...

Steps to reproduce

Register an entity usage with an inline block as the source of the usage. Then, delete the layout builder entity that has the block on it, but don't run cron. Visit the usage page for the used entity.

Proposed resolution

A simple solution is when showing the usage row for an inline block, ask the `InlineBlockUsage` service if there's any usage for the block. If there's not, then don't display it. The downside to this approach is that querying the entity_usage table to get a count of usages for an entity is no longer accurate and will include usage counts for the deleted blocks still.

The other solution would be to delete the entity usage tracking data for the soft-deleted block immediately when its parent is deleted. This would involve some additional code in EntityUsage::deleteBySourceEntity, but I think it might get messy and complex.

Remaining tasks

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Active

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States bkosborne New Jersey, USA

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

Merge Requests

Comments & Activities

Production build 0.71.5 2024