Problem/Motivation
The new core EntityLinks filter (core/modules/filter/src/Plugin/Filter/EntityLinks.php) catches exceptions thrown while resolving a linked entity and tries to log them:
catch (\Exception $e) {
Error::logException('filter', $e);
}However, Drupal\Core\Utility\Error::logException()requires a Psr\Log\LoggerInterfaceas its first argument:
public static function logException(LoggerInterface $logger, \Throwable $exception, ...): void
So instead of logging the original (recoverable) exception, the catch block itself throws a fatal:
TypeError: Drupal\Core\Utility\Error::logException(): Argument #1 ($logger)
must be of type Psr\Log\LoggerInterface, string given, called in
core/modules/filter/src/Plugin/Filter/EntityLinks.php on line 101Because this happens during text rendering, it aborts whatever was rendering the content — in our case it broke the Search API re-indexing batch (HTTP 500 on /batch), but it can break any page render that runs the filter over content whose data-entity-type / data-entity-uuid attributes can't be resolved (e.g. malformed markup such as data-entity-type="true"). The bug effectively defeats the try/catch whose entire purpose is to make the filter resilient.
This code was introduced very recently (commit 5417f19c, 2025-11-20, for issue #3317769 "Add support for linking to entities in CKEditor 5") and the buggy line is still present on 11.x.
Steps to reproduce
On a site with the EntityLinks filter enabled in a text format, create content containing an anchor with a data-entity-type / data-entity-uuid that cannot be resolved to a real entity (e.g. x).
2. Render that content (view the node, or trigger a Search API / rendered-item index batch over it).
3. Observe the request fail with HTTP 500 and the TypeError above instead of the intended logged warning.
Proposed resolution
Pass a real logger to Error::logException(). Minimal one-line change:
catch (\Exception $e) {
Error::logException(\Drupal::logger('filter'), $e);
}(Or, preferably for testability, inject LoggerChannelFactoryInterface / a 'filter' logger channel into the plugin via dependency injection and use that instead of the static \Drupal::logger() call.)
Remaining tasks
• Decide between the minimal `\Drupal::logger('filter')` fix and proper DI of a logger channel into the filter plugin.
• Add a test (kernel/unit) asserting that an unresolvable entity link is logged and the filter returns the original markup instead of throwing.
• Review/MR + commit to 11.x (and backport to supported stable branches that contain the EntityLinks filter).
User interface changes
None.
Introduced terminology
None.
API changes
None. (The fix only corrects an incorrect call to an existing API; no signatures change.)
Data model changes
None.
Release notes snippet
Fixed a fatal TypeError in the EntityLinks filter that occurred when a linked entity could not be resolved: the filter now correctly logs the underlying exception to the filter channel and continues, instead of crashing the render/page request.
| Comment | File | Size | Author |
|---|---|---|---|
| entity-links-logexception-logger.patch | 549 bytes | remco hoeneveld |
Issue fork drupal-3607178
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 #2
remco hoeneveld commentedComment #3
cilefen commentedComment #5
remco hoeneveld commentedComment #6
smustgrave commentedFixes need to land in main first and would see if there’s a test that could be expanded that shows the bug
Comment #8
remco hoeneveld commented@smustgrave good pointers. I have added tests, I have added a version for 11.3 and main, and can confirm that this shows what goes wrong. Again, it's not rocket science what happens, the problem is that Error::logException() needs LoggerInterface $logger, and now a string was passed to it, so when an error occurs, it crashes.
Comment #9
remco hoeneveld commentedComment #10
smustgrave commentedCan actually see on the main branch this failed phpstan. Which is good and means we could probably drop the test on main.
Baseline needs to be updated but are there other instances of this error that may be quick fixes?
Comment #11
dcam commentedMoving to the correct component.