$hook must be of type callable, string given, called in ModuleHandler

Created on 11 April 2025, 29 days ago

Problem/Motivation

I get the TypeError on attempt to launch php core/scripts/drupal server command in a project with a module implementing hook_entity_base_field_info, though I think the problem is in the hook system (it seems like the .module file is not loaded when the hook is being invoked).

TypeError: Drupal\Core\Entity\EntityFieldManager::{closure:Drupal\Core\Entity\EntityFieldManager::buildBaseFieldDefinitions():294}(): Argument #1 ($hook) must be of type callable, string given, called in /app/core/lib/Drupal/Core/Extension/ModuleHandler.php on line 315 in /app/core/lib/Drupal/Core/Entity/EntityFieldManager.php on line 294

Full backtrace is attached in a file.

Steps to reproduce

Linux Mint, PHP 8.4.2 - 8.4.5, Composer 2.8.8, SQLite 3.45.1, Drupal 11.1.6 to the latest dev 11.x

git clone --branch 11.x --depth 1 https://git.drupalcode.org/project/drupal.git .
composer install
composer require drush/drush drupal/token
php core/scripts/drupal quick-start --suppress-login minimal
# Ctrl+C to stop the server for now.
vendor/bin/drush en token
php core/scripts/drupal server --suppress-login

The token module is just an example module implementing the necessary hook to reproduce the issue (entity_base_field_info in this case).

Proposed resolution

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Active

Version

11.0 πŸ”₯

Component

extension system

Created by

πŸ‡ΊπŸ‡¦Ukraine pingwin4eg Zaporizhia πŸ‡ΊπŸ‡¦

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @pingwin4eg
  • πŸ‡ΊπŸ‡¦Ukraine pingwin4eg Zaporizhia πŸ‡ΊπŸ‡¦

    Shield module users experience a similar issue - πŸ› On View TypeError: Drupal\Core\Entity\EntityTypeManager Active .

  • πŸ‡ΊπŸ‡¦Ukraine pingwin4eg Zaporizhia πŸ‡ΊπŸ‡¦

    It seems like the ModuleHandler assumes that .module files of all enabled modules are loaded at the moment of hook invokation, and doesn't try to load them "on-demand".

    On the other hand, the ServerCommand doesn't load .module files too.

    That's weird.

    I'll check older branches of core.

  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    Also it's this a contributed module?

  • πŸ‡ΊπŸ‡¦Ukraine pingwin4eg Zaporizhia πŸ‡ΊπŸ‡¦

    @nicxvan It's not exactly an issue with a contrib module. I think if there was a core module implementing hook_entity_base_field_info in a .module file, the issue would reproduce.

    And πŸ’¬ Drupal 11.2 upgrade causes \Drupal::$container is not initialized yet error Active doesn't help - the same issue even with a patched core.

    I checked core 11.0.x (the latest commit as of now), and there is no error - the .module file is loaded. And there is almost no difference in the ServerCommand between branches. So I guess the actual reason of the error is somewhere in the hook invocation changes in 11.1. I'm going to trace it further.

  • πŸ‡ΊπŸ‡¦Ukraine pingwin4eg Zaporizhia πŸ‡ΊπŸ‡¦

    So I see that in Drupal 11.0.x ModuleHandler loads .module files of all installed modules if there's no cached list of hook implementations:

    EntityFieldManager::buildBaseFieldDefinitions('user')
    ModuleHandler::invokeAllWith('entity_base_field_info', function (callable $hook, string $module) {...})
    ModuleHandler::getImplementationInfo('entity_base_field_info')
    ModuleHandler::buildImplementationInfo('entity_base_field_info')
    ModuleHandler::getHookInfo()
    ModuleHandler::buildHookInfo()
    ModuleHandler::reload()
    ModuleHandler::loadAll() // iterates the list of installed modules and calls
    Extension::load() // includes a .module file if it exists.
    

    This doesn't happen in Drupal 11.x .

  • πŸ‡ΊπŸ‡¦Ukraine pingwin4eg Zaporizhia πŸ‡ΊπŸ‡¦
Production build 0.71.5 2024