CiviCRM has not bootstrapped sufficiently to fire event "hook_civicrm_entity_supported_info"
Overview
The combination of CiviCRM v5.50 + rules
+ entity
+ civicrm_entity
+ de.systopia.campaign
leads to a fatal exception:
CiviCRM has not bootstrapped sufficiently to fire event "hook_civicrm_entity_supported_info"
Reported by @francescbassas on Mattermost https://chat.civicrm.org/civicrm/pl/1izo73dcpjfcbem97eek7s6d6w
Current behaviour
Full backtrace: https://gist.github.com/totten/a40ac137f52301b42706e4f7510bc7ad
There is a root exception, which works like so:
- For whatever normal+circumstantial reason, Civi starts to boot (
civicrm_initialize()
). While booting, it loads extensions (likede.systopia.campaign
). -
campaign.civix.php
has an old-template that raises a warning on php74. (Array and string offset access syntax with curly braces is deprecated
) - Drupal captures the warning, which it sends to the logger.
- The logger is integrated with
rules
, which is further integrated withentity
. Before you can log a warning, it wants to know the list of all entities. - The list of entities includes CiviCRM's entities (core+contrib)... so
civicrm_entity
tries to start Civi again (civicrm_initialize()
), which incorrectly reports that the system has booted (it hasn't; we're still-midboot). It proceeds to ask extensions for their entities (hook_civicrm_entity_supported_info
). -
CiviEventDispatcher
complains (throw new \RuntimeException
) that we are not ready to runhook_civicrm_entity_supported_info
.
There is also a secondary exception:
- The root exception is picked up by Drupal's exception-handler.
- Drupal exception-handler tries to format a pretty page using the theme. A
theme
is a kind ofentity
(apparently). - This fires another request along similar path:
entity
=>civicrm_entity
=>CiviEventDispatcher
=>RuntimeException
Short term mitigations
I suspect any one of the following would address the immediate symptom:
- Fix the syntax warning in
campaign.civix.php
- Disable
de.systopia.campaign
ORrules
ORcivicrm_entity
- Use
php73
Systemic resolutions
A few opinions:
-
rules
makes the logging system too heavy/too complex. One should be able to log a message without triggering a scan of all application-modules. - When Civi boots and loads the ext mainfiles, it is evidently a mistake to trust the CMS with handling warnings. Something in Civi (eg
CRM_Core_Config::singleton()
orcommonBuildModuleList()
) could install a more conservative logger for the duration of bootstrap. -
civicrm_initialize()
should probably report something clearer if you call it recursively (ie call it a second time, mid-boot) -- and thencivicrm_entity
can be more guarded (if the system hasn't booted, then you cannot reliably send hooks to exts) -
CiviEventDispatcher
's interpretation ofnot-ready
could be more conservative; eg instead of throwing an exception, drop the hook and write to the PHPerror_log()
.
I do believe it is correct for the system to complain about this scenario. To see why, suppose we add another extension (advanced_events
) which actually listens to hook_civicrm_entity_supported_info
. It can nominally go through the motions of firing hook_civicrm_entity_supported_info
, but we're mid-boot. We haven't loaded all of the files yet (files like advanced_events.php
). We cannot call advanced_events_civicrm_entity_supported_info()
yet. The hook does not truly run.
To make matters worse, hooks are often tied up with static-caches. Incomplete data will be cached by rules
, entity
, and CRM_Utils_Hook
. Thus, even though the warning in campaign.civix.php
seems recoverable, there would be spooky effects later on. Diagnosing that kind of spooky effect can be extremely difficult (given that each piece works independently; and given how the symptoms depend on the happenstance of local environment).