I'd like to know the best way to delete system menu links. I can't delete them through the UI because they have somehow become stray links (there is no "delete" link next to them).

I've looked at menu_link_delete, which calls _menu_delete_item, but that won't hit if $item['module'] == 'system' unless I force it which is discouraged.

So... if I can't do it through the Drupal API, do I need to do a DB query? If so, which tables should be involved in the delete? Can I get away with just removing records from the menu_links table? It looks like the has_children value may also need to be altered?

Are there other options besides a DB query which I'm not seeing?

I've also seen this answer, but he just moved the stray links to another menu, which I don't want to do.

  • Can I ask what the use case is here? You could simply hide the menu links from appearing if that's a concern. Mar 12, 2015 at 21:00
  • They are already disabled, but even the disabled menu links are causing issues with breadcrumbs. In some cases there are two menu links which point to the same location which is causing the breadcrumbs to break.
    – neuquen
    Mar 12, 2015 at 21:24

2 Answers 2


Rather than deleting the menu items myself through the DB (see here for possible explanation on how), I decided to try to find the underlying issue, and this is what I found:

In my case I have two modules which have the ability to add links to the menu(that I know of...):

  1. Views (/admin/structure/views -> Edit a View -> Page Settings -> Menu)
  2. Pages (/admin/structure/pages -> Edit a Custom Page -> Click on Menu)

The above modules were adding menu items to the menu which cannot be deleted from the menu system unless you go to the modules and remove them first.

In order to remove the menu links I had to do the following:

  1. In the module that creates the menu item (Views, Pages, etc.) set the Menu option to "No Menu".
  2. In the menu config (/admin/structure/menu/manage/), go to the menu item and click on "reset" to remove it from the menu.
  3. Disable the Custom Page or View (the individual view or page, not the entire module)
  4. Re-enable the Custom Page or View
  5. The menu item should no longer be present in the menu_links table.

My issue was related to what seems to be a core problem (see: https://www.drupal.org/node/1058672 OR https://www.drupal.org/node/1029022) which is that if a menu item is created and then removed, it can leave behind a stale record in the menu_links DB table. Disabling the affected Custom Page or View is what actually removed it from the DB for me.


As shown in the example you linked to, you can not only move the menu items to another menu using hook_menu_alter() but also unset them. There is no point in deleting menu links in the database that are defined by enabled modules via hook_menu(). They'll simply repopulate the menu_links table when the menu cache is cleared. Module-defined menu links can be disabled, however.

  • So I would have to unset the links after every menu rebuild with a hook? There has to be a more permanent solution.
    – neuquen
    Mar 13, 2015 at 2:06
  • hook_menu and hook_menu_alter are called every time the menu is built. Using the latter is the way to alter the menu for menu links implemented by other modules. Implement it in a custom module, unset the menu links you don't want to be included in the menu, and you're good to go.
    – montaigne
    Mar 13, 2015 at 2:21
  • yeah, I understand that it is a viable solution, but I'm concerned about performance. Why would I want to unset menu links after every menu rebuild when I could potentially remove them altogether? I know that this alone will not cause very much overhead, but that's what everyone says about every new custom module they create. There will eventually be some overhead. It also sounds like a maintenance nightmare. What if there are hundreds of links that eventually need to be unset??
    – neuquen
    Mar 13, 2015 at 3:15
  • It won't have much impact on performance. A menu is not rebuilt very often. Most modules implement hook_menu, so one more alter hook has a relatively small impact on the performance of a menu rebuild. As for the maintenance issue, I'm having trouble thinking of a need to do this for more than a handful of links.
    – montaigne
    Mar 13, 2015 at 3:30
  • A view's path often conflicts with a system path, so a good example is how the views module handles this in views_menu_alter().
    – montaigne
    Mar 13, 2015 at 3:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.