I just spent hours on the same symptom.
Try disabling all plugins, and look through your functions.php file to see if you have some code that modifies queries.
Don’t know if your underlying issue will be the same, but here’s what the problem was for me:
I had code in my functions.php file that was meant to include custom content types in search results, feeds, etc. (this kind of code could also exist in a plugin you’re using, which is why I suggested turning them off). My code looked like this:
function include_post_types($query) {
global $wp_query;
if ( !is_preview() && !is_singular() && !is_admin() ) {
$post_types = array('post', 'press-releases');
$existing_post_type = get_query_var( 'post_type' ); // Only do this if the post type is not already set
if ( empty( $existing_post_type ) ) {
$query->set( 'post_type' , $post_types );
}
}
return $query;
}
add_filter('pre_get_posts' , 'include_post_types');
Pretty sure I found this code (or something similar) on the forum somewhere, so it’s possible other people are using it. The problem is, it assumes the global wp_query and the query being parsed by pre_get_posts are the same. But in custom queries using the WP_Query object (which the navigation widget and template tag uses), they’re not necessarily the same, and you might accidentally overwrite valid query vars.
I fixed it by doing something I should have done in the first place–removing the reference to the global $wp_query.
function include_post_types( $query ) {
if ( !is_preview() && !is_singular() && !is_admin() ) {
$post_types = array('post', 'press-releases');
$existing_post_type = $query->query_vars['post_type']; // Only do this if the post type is not already set
if ( empty( $existing_post_type ) ) {
$query->set( 'post_type' , $post_types );
}
}
return $query;
}
add_filter('pre_get_posts' , 'include_post_types');
Hope this helps!