Menu links that link to aliases can become corrupt when database updates are run

Created on 3 March 2025, about 2 months ago

Problem/Motivation

When the menu tree is rebuilt during a cache clear that occurs right after database updates (e.g., drush is used with drush updb), the entries for manually added menu links (Menu Link Content entities) that link to a path aliases are registered without a route. While the menu links still get rendered and link to the alias, the active menu trail doesn't work for these pages. This means if you have a menu block setup to render levels 2+ of the active trail, they won't get shown at all.

This happens because in a cache clear (which occurs at the end of the the db update process), the menu router is rebuilt, which also rebuilds the menu trees. Each menu link plugin is asked for its definition, which includes the route and route options (if the link it to a routed path). Menu links that link to internal paths are stored wiht a uri value of internal:/path/alias/name. So MenuLinkContent::getPluginDefinition() checks if the url is routed or not, and to do that it passes the /path/alias/name through PathProcessorManager::processInbound<code>, which loops through all the registered inbound path processors. One of those processors is <code>AliasPathProcessor which converts aliased paths to system paths. But this processor is de-registered via UpdateServiceProvider and doesn't run, so the aliases path if never converted to a routed path.

The menu tree entry for links set up like this have empty values for "route_name" and "route_param_key". This is what leads to issues with menu active trail processing.

A fix is to clear caches again, outside of the update process.

Steps to reproduce

  1. Fresh install of core with standard profile.
  2. Add a Basic Page with alias "/parent-page".
  3. Add a Basic Page with alias "/parent-page/sub-page".
  4. To the main menu, add a menu link labeled "Parent Page" and type in "/parent-page" for the link path
  5. To the main menu, add a menu link labeled "Sub-Page" and type in "/parent-page/sub-page" for the link path. Make it a child of Parent Page.
  6. Visit /parent-page/sub-page in a browser and inspect the <li> of the parent menu link for the parent page. Observe CSS class primary-nav__menu-item--active-trail is present.
  7. Inspect the menu_tree table in the database and look at entries for the parent and sub-page menu links. Observe that the values for route_name and route_param_key show the route info for the node route with the proper IDs.
  8. Add a new post_update hook to system.post_update.php with nothing in it. Doesn't matter, just need one pending update hook.
  9. Visit update.php or use drush updb to run updates.
  10. Visit /parent-page/sub-page in a browser and inspect the <li> of the parent menu link for the parent page. Observe CSS class primary-nav__menu-item--active-trail is missing.
  11. Inspect the menu_tree table in the database and look at entries for the parent and sub-page menu links. Observe that the values for route_name and route_param_key are empty.

Proposed resolution

πŸ› Path aliases are not available in hook_post_update_NAME Active is a related issue and it suggests that we stop removing the AliasPathProcessor from the service container when db updates are being run, as the reason we originally did it ( πŸ› Switch to a null backend for all caches for running the database updates Fixed ) is not relevant anymore.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Active

Version

11.1 πŸ”₯

Component

menu system

Created by

πŸ‡ΊπŸ‡ΈUnited States bkosborne New Jersey, USA

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

Comments & Activities

Production build 0.71.5 2024