diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index 7b72f32604..88b62147cd 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -636,6 +636,12 @@ protected function getImplementationInfo($hook) {
   protected function buildImplementationInfo($hook) {
     $implementations = [];
     $hook_info = $this->getHookInfo();
+
+    // In case it's an early stage and the hook info was loaded from cache, the
+    // module files are not yet loaded at this point and discovery below
+    // produces an empty list.
+    $this->loadAll();
+
     foreach ($this->moduleList as $module => $extension) {
       $include_file = isset($hook_info[$hook]['group']) && $this->loadInclude($module, 'inc', $module . '.' . $hook_info[$hook]['group']);
       // Since $this->implementsHook() may needlessly try to load the include
@@ -685,6 +691,17 @@ protected function buildImplementationInfo($hook) {
    *     from the cache.
    */
   protected function verifyImplementations(&$implementations, $hook) {
+    // Under certain circumstances the module files are not yet loaded. This
+    // happens for example when invoking a hook inside the constructor of a
+    // http_middleware service; these services are constructed very early as
+    // a dependency of http_kernel service. A more concrete example is a
+    // middleware service using the entity_type.manager. Most of the times
+    // the entity type information is retrieved from cache (stored in the
+    // discovery cache bin). When this cache however is missing, hooks
+    // like hook_entity_type_build() and hook_entity_type_alter() need to be
+    // invoked at this early stage.
+    $this->loadAll();
+
     $all_valid = TRUE;
     foreach ($implementations as $module => $group) {
       // If this hook implementation is stored in a lazy-loaded file, include
