Problem/Motivation
Errors on drush updatedb
upgrading domain (2.0.1 => 3.0.0-rc3)
Steps to reproduce
drush updatedb
drush updatedb
Error: Interface "Drupal\language\Config\LanguageConfigFactoryOverrideInterface" not found in /var/www/html/docroot/modules/contrib/domain/domain_config/src/Config/DomainLanguageConfigFactoryOverrideInterface.php on line 10 #0 /var/www/html/vendor/composer/ClassLoader.php(576): include()
#1 /var/www/html/vendor/composer/ClassLoader.php(427): Composer\Autoload\{closure}()
#2 /var/www/html/docroot/modules/contrib/domain/domain_config/src/Config/DomainLanguageConfigFactoryOverride.php(20): Composer\Autoload\ClassLoader->loadClass()
#3 /var/www/html/vendor/composer/ClassLoader.php(576): include('...')
#4 /var/www/html/vendor/composer/ClassLoader.php(427): Composer\Autoload\{closure}()
#5 [internal function]: Composer\Autoload\ClassLoader->loadClass()
#6 /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php(363): class_exists()
#7 /var/www/html/vendor/symfony/dependency-injection/Compiler/RegisterAutoconfigureAttributesPass.php(32): Symfony\Component\DependencyInjection\ContainerBuilder->getReflectionClass()
#8 /var/www/html/vendor/symfony/dependency-injection/Compiler/Compiler.php(80): Symfony\Component\DependencyInjection\Compiler\RegisterAutoconfigureAttributesPass->process()
#9 /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php(768): Symfony\Component\DependencyInjection\Compiler\Compiler->compile()
#10 /var/www/html/docroot/core/lib/Drupal/Core/DrupalKernel.php(1449): Symfony\Component\DependencyInjection\ContainerBuilder->compile()
#11 /var/www/html/docroot/core/lib/Drupal/Core/DrupalKernel.php(972): Drupal\Core\DrupalKernel->compileContainer()
#12 /var/www/html/docroot/core/lib/Drupal/Core/Update/UpdateKernel.php(42): Drupal\Core\DrupalKernel->initializeContainer()
#13 /var/www/html/vendor/drush/drush/src/Drupal/DrupalKernelTrait.php(72): Drupal\Core\Update\UpdateKernel->initializeContainer()
#14 /var/www/html/docroot/core/lib/Drupal/Core/DrupalKernel.php(515): Drush\Drupal\UpdateKernel->initializeContainer()
#15 /var/www/html/vendor/drush/drush/src/Boot/DrupalBoot8.php(210): Drupal\Core\DrupalKernel->boot()
#16 /var/www/html/vendor/drush/drush/src/Boot/BootstrapManager.php(236): Drush\Boot\DrupalBoot8->bootstrapDrupalFull()
#17 /var/www/html/vendor/drush/drush/src/Boot/BootstrapManager.php(377): Drush\Boot\BootstrapManager->doBootstrap()
#18 /var/www/html/vendor/drush/drush/src/Boot/BootstrapManager.php(329): Drush\Boot\BootstrapManager->bootstrapToPhaseIndex()
#19 /var/www/html/vendor/drush/drush/src/Boot/BootstrapHook.php(36): Drush\Boot\BootstrapManager->bootstrapToPhase()
#20 /var/www/html/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php(44): Drush\Boot\BootstrapHook->initialize()
#21 /var/www/html/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php(36): Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->doInitializeHook()
#22 /var/www/html/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php(29): Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->callInitializeHook()
#23 /var/www/html/vendor/consolidation/annotated-command/src/CommandProcessor.php(145): Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->initialize()
#24 /var/www/html/vendor/consolidation/annotated-command/src/AnnotatedCommand.php(378): Consolidation\AnnotatedCommand\CommandProcessor->initializeHook()
#25 /var/www/html/vendor/symfony/console/Command/Command.php(292): Consolidation\AnnotatedCommand\AnnotatedCommand->initialize()
#26 /var/www/html/vendor/symfony/console/Application.php(1121): Symfony\Component\Console\Command\Command->run()
#27 /var/www/html/vendor/symfony/console/Application.php(324): Symfony\Component\Console\Application->doRunCommand()
#28 /var/www/html/vendor/symfony/console/Application.php(175): Symfony\Component\Console\Application->doRun()
#29 /var/www/html/vendor/drush/drush/src/Runtime/Runtime.php(110): Symfony\Component\Console\Application->run()
#30 /var/www/html/vendor/drush/drush/src/Runtime/Runtime.php(40): Drush\Runtime\Runtime->doRun()
#31 /var/www/html/vendor/drush/drush/drush.php(139): Drush\Runtime\Runtime->run()
#32 /var/www/html/vendor/drush/drush/drush(4): require('...')
#33 /var/www/html/vendor/bin/drush(120): include('...')
#34 {main}
Error: Interface "Drupal\language\Config\LanguageConfigFactoryOverrideInterface" not found in include() (line 10 of /var/www/html/docroot/modules/contrib/domain/domain_config/src/Config/DomainLanguageConfigFactoryOverrideInterface.php).
[warning] Drush command terminated abnormally.
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
Issue fork domain-3586509
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:
- 3586509-domain-2.0.1-
changes, plain diff MR !377
Comments
Comment #2
mably commentedHi @pbeltem1, thanks for the report.
From the stack trace this fatal happens during container compilation in
UpdateKernel::initializeContainer(), when Symfony'sRegisterAutoconfigureAttributesPassreflects on every service class. Reflecting onDomainLanguageConfigFactoryOverrideforces PHP to autoloadDomainLanguageConfigFactoryOverrideInterface, which in turn requiresDrupal\language\Config\LanguageConfigFactoryOverrideInterface. That last interface is only resolvable when thelanguagemodule is actually enabled and its namespace is registered.domain_confighas always declareddrupal:languageas a hard dependency, but in 2.0.x no PHP class referenced the language interface at declaration time, so a half-broken install wherelanguageended up missing fromcore.extension.yml(orphaned dep, partial config sync, etc.) would not fatal. In 3.x the newDrupal\domain_config\Config\*class hierarchy makes that dependency load-bearing at compile time.Before we dig further, could you confirm the state of the
languagemodule on the affected site?drush pm:list --status=enabled --no-core | grep -Ei 'language|domain'module:section of the activecore.extension.yml— islanguagelisted?If
languageis not actually enabled, enabling it (drush en language) before runningdrush updatedbshould unblock the upgrade. If it is enabled and the fatal still occurs, that points to a genuine regression on the 3.x branch and we'll need a small reproducer.Comment #4
mably commentedI opened MR !377 with a candidate fix.
The patch drops
autoconfigure: truefrom_defaultsindomain_config/domain_config.services.yml. That directive (added in #3060758) forced Symfony'sRegisterAutoconfigureAttributesPassto reflect on every service class at container-compile time, even though no class indomain_config/src/uses any#[Autoconfigure*]or#[As*]attribute. That eager reflection is what triggers the autoload cascade intoDrupal\language\Config\LanguageConfigFactoryOverrideInterfaceand produces the fatal you reported.With the fix, container compilation no longer touches those classes. The
languageinterface is only autoloaded when theconfig.factoryoverride services are actually instantiated, by which point the kernel has registered all module namespaces.Important caveat: this fix addresses bootstrap-order cases where
languageis enabled but its namespace is not yet registered when the autoconfigure pass runs. Iflanguageis genuinely missing from your activecore.extension.yml, the override services will still fatal later, whenconfig.factorycollects them. So the question I asked previously still matters — could you share the output ofdrush pm:list --status=enabled --no-core | grep -Ei 'language|domain'and themodule:section of your activecore.extension.yml? That will tell us whether your specific site is fully fixed by this MR or whether you also need todrush en languagefirst.Comment #5
mably commentedComment #7
mably commentedUpdate: I closed MR !377 without merging.
The fix I proposed (drop
autoconfigure: truefrom_defaultsindomain_config.services.ymland re-tag event subscribers explicitly) would have moveddomain_configaway from the conventional Drupal pattern. At least 25 core modules use_defaults: autoconfigure: trueand rely on the implicitinstanceof EventSubscriberInterfacetagging — including thelanguagemodule itself, whoselanguage.config_factory_overrideservice is the literal twin of our override classes. Diverging from that idiom to defend against a state Drupal's installer normally forbids is the wrong trade.What's actually happening on your site is that
domain_configis enabled while thelanguagemodule is not.domain_config.info.ymldeclaresdrupal:languageas a hard dependency, so this state is not reachable by normal install/uninstall — it usually comes from a partial config sync, a manual edit ofcore.extension.yml, or a leftover from a much older site state. In 2.0.x nodomain_configclass referenced the language interface at PHP-declaration level, so the broken state was tolerated silently. In 3.x the newDrupal\domain_config\Config\*classes extendDrupal\language\Config\LanguageConfigFactoryOverrideInterface, and container compilation fatals as soon as Symfony's autoconfigure pass reflects on those classes.The fix on your side is straightforward:
languageis missing: check themodule:section of your activecore.extension.yml, or rundrush pm:list --status=enabled --no-core | grep -Ei 'language|domain'.drush en language.drush updatedbas usual.If
languageturns out to actually be enabled and the fatal still happens, please reopen with the output above — that would point to a different bootstrap-order issue worth investigating. Otherwise I'll mark this issue as works as designed: the dependency has always been hard, 3.x just makes its absence load-bearing.A small follow-up that would make this failure mode less cryptic for the next person — adding a
#[Hook('install_requirements')]/#[Hook('update_requirements')]check indomain_config.installthat surfaces a clear error iflanguageis missing — is worth opening as a separate issue.Comment #8
mably commentedFollowup: I opened #3588828 to track splitting
domain_configanddomain_config_uiinto base modules and language-aware companions, so that monolingual sites can use the domain-only override features without ever installing thelanguagemodule. That refactor would also make this exact failure mode unreachable on a fresh install.EDIT: The split has been merged,
domain_configcan now be used without thelanguagemodule.Comment #9
mably commented