ExtraFieldBlockCacheTagInvalidator is tagged cache_tags_invalidator, so it's created together with cache_tags.invalidator. It gets plugin.manager.block in its constructor, and the block manager gets logger.channel.default. So anything that needs cache_tags.invalidator while the default logger channel is being created ends in a ServiceCircularReferenceException.

For us it broke drush on a cold container (11.4.7):

Circular reference detected for service "logger.channel.default", path: "Drupal\Core\Recipe\Command\RecipeCommand -> logger.channel.default -> Drupal\menu_link_content\Hook\MenuLinkContentHooks -> plugin.manager.menu.link -> Drupal\Core\Menu\MenuTreeStorageInterface -> cache_tags.invalidator -> plugin.manager.block"

From the trace: tmgmt_smartling_log_settings replaces the logger channel factory, and its LoggerChannel constructor reads config. On a cold cache the domain config overrider then loads the domain storage, the entity type definitions get built, and hook_entity_type_alter() instantiates MenuLinkContentHooks → plugin.manager.menu.link → menu tree storage → cache_tags.invalidator → layout_builder.extra_fields.invalidator → plugin.manager.block → logger.channel.default again.

Reading config while creating a logger channel isn't great either, but other contrib loggers ran into the same loop and worked around it on their side: filelog #3416342: Circular reference detected for service, raven #3269293: Circular reference detected for service (the error goes away when Layout Builder is uninstalled), watchdog_mailer #3414001: Site crashing with services circular references, commerce #3587604: Circular reference detected for service "Drupal\Core\Logger\LoggerChannelFactoryInterface".

The invalidator only needs the block manager when entity_field_info is invalidated. Proposed fix: inject a service closure (#[AutowireServiceClosure('plugin.manager.block')]) and only resolve it inside invalidateTags() for that tag. The class is @internal, so no BC layer needed.

Patch attached for 11.4.x (uses !service_closure in the YAML, on main the service is autowired so the MR will use the attribute). For a kernel test: a test module with a logger that depends on cache_tags.invalidator, and check that logger.channel.default can be fetched.

Issue fork drupal-3632318

Command icon 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

bceyssens created an issue. See original summary.

bceyssens’s picture

Issue summary: View changes

bceyssens’s picture

Status: Active » Needs review
smustgrave’s picture

Status: Needs review » Needs work
bceyssens’s picture

Status: Needs work » Needs review

#3103620 does not fix this. I applied !14205 on main without !17545 and ran the kernel test from !17545. It still fails:

Circular reference detected for service "logger.channel.default", path: "logger.channel.default -> logger.factory -> logger.layout_builder_logger_test -> cache_tags.invalidator -> plugin.manager.block".

With !17545 added on top, it passes.

!14205 only changes the syslog logger. Our site does not have syslog enabled. The logger in our trace is from tmgmt_smartling_log_settings, which reads config in its constructor. filelog, raven, watchdog_mailer and commerce hit the same loop with their own loggers. #3609333 (closed as a duplicate of #3103620) shows the same tail: cache_tags.invalidator -> plugin.manager.block -> logger.channel.default.

!17545 removes the plugin.manager.block dependency from cache_tags.invalidator. It does not depend on what a logger does in its constructor. Both issues can be committed independently.

Generated with the help of an LLM.

smustgrave’s picture

Sharing this as this is the 10th maybe issue I’ve seen with an AI post. Please review much appreciated

https://www.drupal.org/docs/develop/issues/issue-procedures-and-etiquett...