Problem/Motivation
Local task tabs that are derived from overridable configuration are cached without an "active domain" axis, so their output leaks across domains. The user-visible symptom is on /admin/structure/block: the "default theme" tab (derived by Drupal\block\Plugin\Derivative\ThemeLocalTask) shows the same theme name on every domain, even when each domain has a different system.theme.default override registered through domain_config_ui.
Example on a multi-domain instance with system.theme registered as overridable:
- Domain A:
system.themeoverride —default = olivero - Domain B:
system.themeoverride —default = drupal11 - Domain C:
system.themeoverride —default = bootstrap5
Visiting /admin/structure/block on each domain shows the same first tab everywhere instead of "Olivero" / "Drupal 11" / "Bootstrap5" respectively. Whichever domain hits the cache cold first wins for everyone.
Steps to reproduce
- Install
domain,domain_config,domain_config_ui. - Register
system.themeas overridable for at least two domains. - Save a different default theme per domain.
- Clear caches.
- Visit
/admin/structure/blockon each domain in turn — the "default theme" tab name does not change.
Root cause
Drupal\Core\Menu\LocalTaskManager sets its plugin definition cache key based on language only:
// core/lib/Drupal/Core/Menu/LocalTaskManager.php $this->setCacheBackend($cache, 'local_task_plugins:' . $language_manager->getCurrentLanguage()->getId(), ['local_task']);
Derivers like ThemeLocalTask read system.theme.default via themeHandler->getDefault(), which IS domain-overridden — but the resulting plugin definitions are cached under a key that does not include the active domain id. The first domain to populate the cache freezes the answer for the rest.
Proposed resolution
Decorate plugin.manager.menu.local_task in the domain module so the plugin definition cache key includes the active domain id, e.g. local_task_plugins:LANGCODE:DOMAIN_ID (where LANGCODE is the active interface language and DOMAIN_ID is the active domain machine name). Alternative: invalidate the local_task cache tag on domain switch — works but evicts more than necessary on every domain change.
Remaining tasks
- Decide between cache-key decoration vs tag-invalidation.
- Patch + functional test that asserts the "default theme" tab title differs across two domains with distinct
system.themeoverrides. - Audit other plugin managers that cache discovery output keyed only by language for the same class of bug (menu links, local actions, contextual links, etc.).
Related
- #3587744 — separate but adjacent: per-domain config display on EntityForm and admin lists.
Issue fork domain-3588057
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:
- 3588057-local-task-cache-domain
changes, plain diff MR !367
- 3588057-local-task-tabs
compare
Comments
Comment #3
mably commentedComment #5
mably commentedClosing as won't fix in favour of the submodule-scoped fix in
domain_extras: #3588108 (!33).Reasons for not landing the cache-key change in
domain's base module:language × domain × manager. Three managers (LocalTaskManager,LocalActionManager,ContextualLinkManager) × N domains × M languages compounds quickly. Sites that don't need it shouldn't pay for it.domain_extraspattern.domain_config_entity_uiis already an opt-in submodule for the read-side / list-builder fold;domain_menu_extrasfollows the same shape: install the submodule, get the fix.MR !367 will be closed. Tracking work continues in #3588108.