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

Created on 11 April 2025, 5 months 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 πŸ‡ΊπŸ‡¦
  • πŸ‡ΊπŸ‡ΈUnited States nicxvan

    Are you able to provide a test case so we can reproduce and fix this?

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

    @nicxvan

    It can be reproduced by following steps in the issue summary. I can write a test case, but I can't promise it'll be fast.

  • πŸ‡¨πŸ‡¦Canada Charlie ChX Negyesi 🍁Canada

    I can trace this if needed but I will bet you anything the problem is Drupal\Core\Command\InstallCommand not flushing caches after install -- this could be hardwired in the command or added to install_tasks.

  • Issue was unassigned.
  • Status changed to Needs review about 1 month ago
  • πŸ‡ͺπŸ‡ΈSpain rzb Barcelona

    Hi,
    I ran into the same exact issue, and I made a very basic patch to ensure the hook function is callable before actually calling the callback.

  • πŸ‡©πŸ‡ͺGermany mkalkbrenner πŸ‡©πŸ‡ͺ

    We ran into the same issue when upgrading a Drupal 10 site to 11.2. drush cr solves the issue temporarily, but it happens often.

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

    Can you share the list of modules you have installed in an attachment?

    Does anything in particular trigger it?

  • πŸ‡©πŸ‡ͺGermany cspitzlay πŸ‡©πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Re #12: This will prevent crashing, but will the result be correct?
    I think the hook does need to be called.

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

    Don't see any MR to review

  • πŸ‡²πŸ‡ΊMauritius amyesther

    Hello, I can reproduce this error after upgrading to Drupal 11.
    I have a middleware that calls $node->access() for access checks and redirections. In Drupal 11, for the access method to work correctly, I had to manually load several modules (system, node, scheduler_content_moderation_integration, quick_node_clone, unpublished_node_permissions).

    However, if I import the configurations and access a page without clearing the cache, the error still occurs, and applying the patch #12 results in the following issue: https://www.drupal.org/project/drupal/issues/2701575 πŸ› RequestContext throws error when current request is empty Needs work .
    Is there a proper way to perform node loading / access checks in middleware with Drupal 11?

  • πŸ‡§πŸ‡·Brazil thiagomoraesp

    Same here after delete any field on user entity, but other work colleagues with same code base and same initial database copy can't reproduce, it happens only on my machine no matter how many times i rebuild my local instance, don't know why.

    The #12 patch solve this problem but start to trigger a paragraphs problem.

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

    Patch #12 ignores the problem, doesn't solve it. I proposed the solution in the issue summary - load (include/require) the .module file.

    The problem is only with legacy hook functions.

    I'll try to dedicate some time to this issue, though it doesn't a problem anymore on the project I'm working on (I don't use the PHP built-in server anymore).

  • πŸ‡¬πŸ‡§United Kingdom catch

    @amyesther loading a node in a middleware isn't really supported or encouraged, see πŸ› ModuleHandler skips all hook implementations when invoked before the module files have been loaded Needs review and πŸ› Shield middleware invokes hooks before modules are loaded, corrupting module_implements cache Needs work for some discussion. There are other request events you could hook into if you really need the logic to run early in every request (just not so early that modules aren't loaded yet).

Production build 0.71.5 2024