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

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

pbeltem1 created an issue. See original summary.

mably’s picture

Status: Needs review » Postponed (maintainer needs more info)
Issue tags: -domain (2.0.1 => 3.0.0-rc3) drush updatedb

Hi @pbeltem1, thanks for the report.

From the stack trace this fatal happens during container compilation in UpdateKernel::initializeContainer(), when Symfony's RegisterAutoconfigureAttributesPass reflects on every service class. Reflecting on DomainLanguageConfigFactoryOverride forces PHP to autoload DomainLanguageConfigFactoryOverrideInterface, which in turn requires Drupal\language\Config\LanguageConfigFactoryOverrideInterface. That last interface is only resolvable when the language module is actually enabled and its namespace is registered.

domain_config has always declared drupal:language as a hard dependency, but in 2.0.x no PHP class referenced the language interface at declaration time, so a half-broken install where language ended up missing from core.extension.yml (orphaned dep, partial config sync, etc.) would not fatal. In 3.x the new Drupal\domain_config\Config\* class hierarchy makes that dependency load-bearing at compile time.

Before we dig further, could you confirm the state of the language module on the affected site?

  • drush pm:list --status=enabled --no-core | grep -Ei 'language|domain'
  • The module: section of the active core.extension.yml — is language listed?
  • Drupal core version and PHP version.

If language is not actually enabled, enabling it (drush en language) before running drush updatedb should 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.

mably’s picture

I opened MR !377 with a candidate fix.

The patch drops autoconfigure: true from _defaults in domain_config/domain_config.services.yml. That directive (added in #3060758) forced Symfony's RegisterAutoconfigureAttributesPass to reflect on every service class at container-compile time, even though no class in domain_config/src/ uses any #[Autoconfigure*] or #[As*] attribute. That eager reflection is what triggers the autoload cascade into Drupal\language\Config\LanguageConfigFactoryOverrideInterface and produces the fatal you reported.

With the fix, container compilation no longer touches those classes. The language interface is only autoloaded when the config.factory override services are actually instantiated, by which point the kernel has registered all module namespaces.

Important caveat: this fix addresses bootstrap-order cases where language is enabled but its namespace is not yet registered when the autoconfigure pass runs. If language is genuinely missing from your active core.extension.yml, the override services will still fatal later, when config.factory collects them. So the question I asked previously still matters — could you share the output of drush pm:list --status=enabled --no-core | grep -Ei 'language|domain' and the module: section of your active core.extension.yml? That will tell us whether your specific site is fully fixed by this MR or whether you also need to drush en language first.

mably’s picture

Component: Miscellaneous » - Domain Config
Status: Postponed (maintainer needs more info) » Needs review

mably’s picture

Status: Needs review » Postponed (maintainer needs more info)

Update: I closed MR !377 without merging.

The fix I proposed (drop autoconfigure: true from _defaults in domain_config.services.yml and re-tag event subscribers explicitly) would have moved domain_config away from the conventional Drupal pattern. At least 25 core modules use _defaults: autoconfigure: true and rely on the implicit instanceof EventSubscriberInterface tagging — including the language module itself, whose language.config_factory_override service 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_config is enabled while the language module is not. domain_config.info.yml declares drupal:language as a hard dependency, so this state is not reachable by normal install/uninstall — it usually comes from a partial config sync, a manual edit of core.extension.yml, or a leftover from a much older site state. In 2.0.x no domain_config class referenced the language interface at PHP-declaration level, so the broken state was tolerated silently. In 3.x the new Drupal\domain_config\Config\* classes extend Drupal\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:

  1. Confirm language is missing: check the module: section of your active core.extension.yml, or run drush pm:list --status=enabled --no-core | grep -Ei 'language|domain'.
  2. Enable it: drush en language.
  3. Then run drush updatedb as usual.

If language turns 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 in domain_config.install that surfaces a clear error if language is missing — is worth opening as a separate issue.

mably’s picture

Followup: I opened #3588828 to track splitting domain_config and domain_config_ui into base modules and language-aware companions, so that monolingual sites can use the domain-only override features without ever installing the language module. That refactor would also make this exact failure mode unreachable on a fresh install.

EDIT: The split has been merged, domain_config can now be used without the language module.

mably’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.