For my custom module, when add one of its pages to shorcuts list and then disable the module, get the following exception on all pages.

Symfony\Component\Routing\Exception\RouteNotFoundException: Route "some_module.config_list" does not exist. in Drupal\Core\Routing\RouteProvider->getRouteByName() (line 150 of core/lib/Drupal/Core/Routing/RouteProvider.php).

The exception disappears when corresponding row is removed from database shortcut table.

CommentFileSizeAuthor
#7 shortcut-route-not-found-2266325-7.patch2.5 KBmr.baileys
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] Unable to apply patch shortcut-route-not-found-2266325-7.patch. Unable to apply patch. See the log in the details link for more information. View
#3 shortcut-route-not-found-2266325-3.patch1.07 KBmr.baileys
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 68,326 pass(es), 1 fail(s), and 0 exception(s). View
Members fund testing for the Drupal project. Drupal Association Learn more

Comments

kpv’s picture

Issue summary: View changes
kpv’s picture

Issue summary: View changes
mr.baileys’s picture

Priority: Normal » Major
Status: Active » Needs review
FileSize
1.07 KB
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] 68,326 pass(es), 1 fail(s), and 0 exception(s). View

I set out to automatically remove shortcut links to routes belonging to modules that are being uninstalled, but I don't know how to get a list of routes registered by any given module.

To advance this issue, here's a test that shows this bug. (setting to NR to run this test through the testbot, expecting a fail.)

Setting to major since uninstalling a module can break your entire site, and requires manually removing the shortcut link from the database to recover.

Status: Needs review » Needs work

The last submitted patch, 3: shortcut-route-not-found-2266325-3.patch, failed testing.

kpv’s picture

#3 mr.baileys
I see two ways to solve the issue:

  1. As you mentioned, we could remove routes for the module uninstalled. For that YamlDiscovery class could be used (see RouteBuilder::rebuild and RouteBuilder::getRouteDefinitions for more info). Maybe there is another way.
  2. Compare routes in shortcut and in router at hook_modules_uninstalled. If route doesn't exist in router then remove it from shortcut as well.

Imo, 2nd option is a better one.

kpv’s picture

Version: 8.0-alpha11 » 8.x-dev
mr.baileys’s picture

Status: Needs work » Needs review
FileSize
2.5 KB
FAILED: [[SimpleTest]]: [PHP 5.4 MySQL] Unable to apply patch shortcut-route-not-found-2266325-7.patch. Unable to apply patch. See the log in the details link for more information. View

@kpv: thanks for the pointers!

Attached is a patch that should fix the original scope of this issue (uninstalling a module with routes for which one or more shortcut links exist no longer cause the site to break). However, this does not solve the full issue: routes can be added dynamically (for example through Views), and shortcut links pointing to those might still trigger an exception when the routes disappear (which is also why the router/shortcut-table solution outlined in #5.2 might not be the best approach).

For dynamic routes, I think we have no other option than to add a check to shorcut to ensure all links to be rendered point to a route that exists.

Setting to CNR to show that the patch fixes the "shortcut-breaks-on-module-uninstall"-issue, but this issue remains NW for the dynamic routes.

dawehner’s picture

+++ b/core/modules/shortcut/shortcut.module
@@ -438,3 +440,26 @@ function shortcut_toolbar() {
+  // Fetch all routes declared in the modules being uninstalled.
+  $yamlDiscovery = new YamlDiscovery('routing', $module_directories);
+  $routes = $yamlDiscovery->getDefinitions();
+
+  // Remove shortcut links pointing to routes that belong to the modules being
+  // uninstalled.
+  if ($routes) {
+    $shortcuts = \Drupal::entityQuery('shortcut')->condition('route_name', array_keys($routes), 'IN')->execute();
+    entity_delete_multiple('shortcut', $shortcuts);
+  }

Mh, this really just works for static routes, not defined dynamically. An alternative implementation could be to fetch all the route names which are available and check with those

dawehner’s picture

Status: Needs review » Needs work

So .

tim.plunkett’s picture

This is absolutely a duplicate of an old issue, but I can't find it :(

dawehner’s picture

Yeah I also remember that other one, but I thought it was already marked as fixed ...

kpv’s picture

@tim.plunkett, @dawehner
#2277753: Shortcuts should handle missing routes elegantly seems to be the duplicate and #2200185: Router table is not cleared when modules are uninstalled deals with a similar issue.

gendoas’s picture

In function shortcut_renderable_links() you may ensure that only available routes are listed. This does not remove items from disabled modules in database, but prevents errors.

function shortcut_renderable_links($shortcut_set = NULL) {
  // ...
  /** @var \Drupal\shortcut\ShortcutInterface[] $shortcuts  */
  $route_provider = \Drupal::service('router.route_provider');
  $shortcuts = \Drupal::entityManager()->getStorage('shortcut')->loadByProperties(array('shortcut_set' => $shortcut_set->id()));
  $all_cache_tags = array();
  foreach ($shortcuts as $shortcut) {
    // ensure route exists
    if ($route_provider->getRoutesByNames(array($shortcut->route_name->value))) {
      $links[] = array(
        'title' => $shortcut->label(),
        'href' => $shortcut->path->value,
      );
      $all_cache_tags[] = $shortcut->getCacheTag();
    }
  }
  // ...
  return $shortcut_links;
}

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 7: shortcut-route-not-found-2266325-7.patch, failed testing.

dawehner’s picture

Status: Needs work » Closed (duplicate)