I'm working on a site where some of the nav menu items disappear (from the front end, the back end, and the database). However, debugging is extremely difficult since they don't disappear immediately! As a result, I'm unable to figure out what's triggering the deletion.

More info:

  • It seems as though nav menu items that are of the 'custom' variety (e.g. to an arbitrary url, rather than a post/page/category etc.) might be safe. I'm not 100% sure about that yet.
  • At one point, new nav menu items were not being saved - I'd add several to a menu, click "Save Menu", and the menu would be saved with no menu items.

Any suggestions on how to debug this particularly frustrating problem?

This is on 3.4.1. I've just updated to 3.4.2, but I can't verify yet today that it's still happening (although I've no reason to believe it won't).

Edit: I have confirmed that "custom" nav items (links to arbitrary url, vs. a WP page/category/etc.) do not get deleted.

  • 1
    Checked Ticket #14134?
    – fuxia
    Sep 7, 2012 at 15:46
  • Unfortunately it's not that bug - this happens with just a few menu items. Sep 7, 2012 at 16:08
  • does it happen with javascript off?
    – ifdion
    Sep 8, 2012 at 1:36
  • @ifdion - what would javascript have to do with items being deleted from the database? Sep 12, 2012 at 18:56
  • my bad, thought it was disappearing from the front end only
    – ifdion
    Sep 12, 2012 at 22:24

2 Answers 2


Log queries

As the question says "it doesn't happen always", it's hard to tell what's really going on. When you can't see what happens (query in background) and don't know when it happens, then it's best to log it.

The logger

On activation, the plugin will try to create a log directory named 'nav_log' in the temp folder - it will throw and print an error, when this doesn't work.

It will then try to write to a file named 'nav_log.txt' inside the temp dir. You should get a log entry each time, a query for a nav_menu_item is triggered. The logs will be prefixed by the date (Y-m-d g:i:s). So, as long as you keep your eyes open and try to catch changes in the UI, you should be able to tell when and it happens. I also added the $hook_suffix global to (maybe) help determining when this happens.

Disclaimer: The plugin needs some love and won't work out of the box. Filesystem stuff is complicated and the plugin is just a sketch/an idea.

! defined( 'ABSPATH' ) AND exit;
/** Plugin Name: (#64487) »kaiser« log nav menu query */
# Version: 2012-09-17.0924

if ( ! class_exists( 'wpse64487_query_logger' ) )
    register_activation_hook( __FILE__, array( 'wpse64487_query_logger', 'create_log_dir' ) );
    add_action( 'plugins_loaded', array( 'wpse64487_query_logger', 'init' ), 5 );

class wpse64487_query_logger
    public static $instance;
    public $name = 'nav_log';

    public static function init()
        null === self :: $instance AND self :: $instance = new self;
        return self :: $instance;

    public function __construct()
        add_filter( 'posts_where', array( $this, 'ask_where' ) );

    public function create_log_dir()
        $output = true;
        // Relative to the Temp Dir
        if ( ! wp_mkdir_p( $this->get_log_loc() ) )
            $output = new WP_Error( __CLASS__, 'Log Dir creation failed.' );

        is_wp_error( $output ) AND print $output->get_error_message( __CLASS__ );

    public function get_log_loc( $full = false )
        $output = trailingslashit( get_temp_dir()."{$this->name}" );
        $full AND $output .= "{$this->name}.txt";
        return $output;

    public function ask_where( $where )
        if ( "`post_type` = 'nav_menu_item'" === $where )
            add_filter( 'posts_clauses', array( $this, 'catch_query' ) );
        return $where;

    public function catch_query( $pieces )
        global $wp_filesystem, $hook_suffix;
        $file = $this->get_log_loc( true );
        $contents  = $wp_filesystem->get_contents( $file );
        // Append current query
        $contents .= "\n\n@".date( "Y-m-d g:i:s" );
        $contents .= "\n Query: ".implode( ' ', $pieces );
        $contents .= "\n Page: {$hook_suffix}";
        return $pieces;
} // END Class wpse64487_query_logger

} // endif;

Have you de-activated any plugins you may have installed?

If you've already tried that and it's still happening then I can't recommend a simple fix with this install, but have you tried, or even considered, backing up your existing install, exporting your content to an xml file and re-installing with a clean database and no plugins activated to begin with, just you're desired theme? The new install should have standard (non-custom code) in the core files. Before importing your content back in, try setting up a menu and see if it still happens. If it does, you can rule out a corrupted database and I think it'd be safe to say the problem lies somewhere in your theme files.

Just remember to make a note of your current core options values before wiping them out with a clean install.

  • I only have a few plugins installed, and they're all "safe" plugins. However, I have plenty of custom code in my theme and mu-plugins directories. My challenge is to figure out how to debug the issue, given the random/intermittent nature of the problem. Sep 12, 2012 at 21:11
  • Ok but I wouldn't rule out the possibility of a corrupted database. I'm not sure how it could happen or entirely sure how it could affect the menus, but the transient settings in the options table might be one possible cause. Maybe they've been changed at some point?
    – Ben
    Sep 13, 2012 at 5:41
  • As this doesn’t answer the question … it should be a comment, right?
    – fuxia
    Sep 16, 2012 at 14:18

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.