Problem/Motivation

On a plain Drupal CMS base the install completes, and then every page returns HTTP 500 — including /user/login and /admin/config/development/performance, so there is no route to recovery from the UI:

PluginNotFoundException: The "redirect" entity type does not exist.
  in Drupal\Core\Entity\EntityTypeManager->getDefinition() (line 171)
  Drupal\trash\TrashEntityTypeManager->getHandler()   [via RedirectPrefixList]

drush watchdog:show --severity=Error reports 22 php errors after the install, naming two missing entity type definitions: redirect and ultimate_cron_job.

The content import itself succeeds — 26 blog, 12 country, 24 event, 3 page and 5 program nodes, 8 Canvas pages, 74 media items and 25 taxonomy terms are all present. Immediately after the install drush also reports stale values: theme stark, page.front of /user/login, and 66 modules.

A single drush cr clears the whole failure: the theme resolves to vartheme_bs5_horizonaid, page.front becomes /page/4, the module count goes from 66 to 373, and every page returns 200. So the defect looks like post-install container/cache state rather than missing config, but that is not yet proven.

Root cause is not yet established

This is filed as an observation with evidence, not as a diagnosis:

  • It is not established why the redirect and ultimate_cron_job entity type definitions are absent from the container at the end of the install while their modules are evidently installed.
  • The failure varies between runs of the same recipe commit (088941e). An earlier fresh install of that same commit failed instead with the Canvas OutOfRangeException of #3620437, with the block component pins already resolved and no redirect error at all. Two fresh installs of one commit produced two different site-wide 500s.
  • Not reproduced on a Varbase base: a fresh install of the same recipe commit on drupal/varbase_project:11.0.x-dev logged zero errors matching "does not exist", and its drush readings were already correct before any cache rebuild.

Steps to reproduce

mkdir my-drupal-site-horizonaid1 && cd my-drupal-site-horizonaid1
ddev config --project-type=drupal11 --docroot=web
ddev start -y
ddev composer create-project drupal/cms
ddev composer config minimum-stability dev
rm composer.lock
ddev composer require drupal/horizonaid:1.0.x-dev
  1. Install through the browser installer, picking the Horizon Aid site template. All 122 batch operations complete and the installer redirects to the finish URL.
  2. Visit any page, including /user/login — all 500 with the exception above.
  3. Run ddev drush watchdog:show --severity=Error — 22 php errors, naming redirect and ultimate_cron_job.
  4. Run ddev drush cr — every page returns 200 and all readings correct.

Because the outcome varies per run, reproduce on a fully fresh build and install each time: a reused codebase or database lets a previous run's state mask it.

Proposed resolution

To be determined once the cause is established. Directions worth checking, in order:

  • Whether the recipe's module install order leaves redirect and ultimate_cron enabled but their entity type definitions uncached, and whether a cache rebuild belongs at the end of the recipe rather than being left to the site builder.
  • Whether trash's TrashEntityTypeManager decorator resolving RedirectPrefixList during install is the actual trigger, in which case this may belong upstream rather than here.
  • Whether this is specific to a Drupal CMS base carrying a different module set than a Varbase base, where it does not reproduce.

Worth noting for triage: whatever the fix, a site-wide 500 that also takes out /user/login leaves a site builder with no UI recovery path, which is what makes this Major rather than Normal.

Remaining tasks

  • ✅ File an issue
  • ❌ Establish the root cause
  • ❌ Addition/Change/Update/Fix
  • ❌ Testing to ensure no regression
  • ➖ Automated unit/functional testing coverage
  • ➖ Developer Documentation support
  • ➖ User Guide Documentation support
  • ➖ UX/UI designer responsibilities
  • ➖ Accessibility and Readability
  • ❌ Reviewed by a human
  • ❌ Code review by maintainers
  • ❌ Full testing and approval
  • ❌ Credit contributors
  • ❌ Review with the product owner
  • ❌ Update Release Notes
  • ❌ Release

User interface changes

  • N/A

API changes

  • N/A

Data model changes

  • N/A

Release notes snippet

  • N/A

Comments

rajab natshah created an issue.

rajab natshah’s picture

Reproduced four times on plain Drupal CMS, and narrowed with a control test.

Environment: drupal/cms built with composer create-project, then composer config minimum-stability dev and composer require drupal/horizonaid:1.0.x-dev. Drupal core 11.4.6, drupal/canvas 1.11.0, PHP 8.4, DDEV, MariaDB. No patches of any kind — no vardot/varbase-patches, no vardot/drupal-core-patches.

  1. Only the browser installer is affected. drush site:install recipes/horizonaid and drush site:install drupal_cms_installer installer_site_template_form.add_ons=horizonaid both exit 0 on the identical codebase, with zero warnings and zero PHP errors logged, and the resulting site serves every route. Clicking through the Drupal CMS installer and picking Horizon Aid leaves a site-wide HTTP 500 — every route, including the front page and /user/login.

  2. Control test: Drupal CMS's own Byte template installs fine through the same browser installer, on the same build, minutes apart. It finished with system.theme.default set to byte_theme, and / and /user/login both HTTP 200. So the browser installer itself works; the failure is specific to this template.

  3. The batch does not crash — it reports success. In the nginx access log every batch request is a 200, then op=do_nojs&op=finished returns 303, the installer redirects, and /admin/dashboard/welcome returns 500. There is no timeout and no fatal in the batch requests; the batch table is empty afterwards, i.e. the batch completed normally. PHP is not the limit: FPM has max_execution_time = 600 and memory_limit = 1024M, the batch column is longblob, and max_allowed_packet is 256MB.

  4. It stops at a different point every run, which is why this is easy to mistake for a hang: across four runs the finished site had 77, 146, 178 and 159 of the 245 modules a drush install produces.

  5. What lands and what does not. The recipe's config and content DO apply — 70 nodes, 8 Canvas pages, 74 media, 25 taxonomy terms, the site name, and system.site page.front resolved from /home to /page/4, which proves the RecipeAppliedEvent ran. But extensions are missing, including vartheme_bs5_horizonaid (so system.theme.default stays stark, which is not installed either), plus varbase_components, drupal_cms_search, canvas_page_template_component and metatag_views. Installed themes were only claro, gin, canvas_stark, easy_email_theme.

  6. The 500 itself is a config-without-its-module state left by that partial apply. Two different first fatals were seen, depending on where the run stopped:

    • PluginNotFoundException: The "redirect" entity type does not exist — redirect.settings, views.view.redirect, views.view.redirect_404 and language.content_settings.redirect.redirect imported while the redirect module was never installed.
    • PluginNotFoundException: The "metatag_display_extender" plugin does not exist. Valid plugin IDs for Drupal\views\Plugin\ViewsPluginManager are: default — views.settings.display_extenders contains metatag_display_extender while metatag_views is not installed. Every Views render then fatals, which is why the whole site 500s rather than one page.

The pattern in 3, 4 and 5 together — a batch that reports success having executed a varying subset of the recipe's operations — is the part worth chasing. It is not a timeout and not a crash.

The drush paths are unaffected by any of this and remain a working install route today.

AI-Generated: Yes — this investigation was assisted by Claude Code (Claude Opus 5); every command and install run reported above was executed locally.

rajab natshah’s picture

Correction to my previous comment. Points 3, 4 and 5 of #comment-16765888 are wrong, and the earlier comment on this issue (#comment-16757196) was right: drush cr clears the 500 immediately.

What I got wrong and why: I measured the installed module list and the default theme with drush while the site was in its post-install state, and read those values back as evidence that the recipe had only partly applied. They were stale cached values. Running drush cr on the same broken site changed the readings from "159 of 245 modules, system.theme.default still stark" to the complete, correct install. So the varying module counts I reported across four runs (77, 146, 178, 159) were not the installer executing a varying subset of its operations — they were a stale configuration cache being read four times. There is no partial apply, and nothing is skipped.

What is actually true, verified after a cache rebuild on the same site that had been returning 500 on every route:

  • drush cr alone takes the site from HTTP 500 on every route to HTTP 200 on /, /about, /countries, /programs, /donate, /resources, /events and /impact, and on /user/login.
  • The install had in fact completed correctly: 245 modules, system.theme.default is vartheme_bs5_horizonaid, the drupal_cms_installer profile has been uninstalled as it should be, metatag_views and varbase_components are both installed, and the content is all present — 70 nodes, 8 Canvas pages, 74 media.

So the defect is narrower than I described: a Horizon Aid install through the Drupal CMS browser installer finishes correctly but leaves a stale cache, and every route fatals until caches are rebuilt. The first fatal seen depends only on which cached plugin definition is consulted first — PluginNotFoundException for the redirect entity type in one run, for the metatag_display_extender Views plugin in another. Both are symptoms of the stale cache, not of missing modules.

What stands from the previous comment: point 1 (only the browser installer is affected; both drush paths finish clean and serve every route) and point 2 (Drupal CMS's own byte template installs through the same browser installer on the same build, minutes apart, and serves normally without any cache rebuild). Point 3's observation that the batch does not crash — every batch request 200, op=finished returning 303, an empty batch table afterwards — also stands, and now reads as consistent with a completed install rather than a truncated one.

Environment unchanged: plain drupal/cms, drupal/horizonaid:1.0.x-dev, Drupal core 11.4.6, drupal/canvas 1.11.0, PHP 8.4, DDEV, MariaDB, no patches of any kind.

AI-Generated: Yes