I just started noticing when I hit a page not found url, the primary_links and other navigation menus blocks disappear! This is not good because the user get confused looking at a screen of "Page not found" and there is no navigation links anywhere. Sure, the user should hit the back button but we should not rely on that. It's also not consistent because on the "Access denied" page, all the links are there.
Check it out on drupal.org: try http://www.drupal.org/junk, the right hand nav blocks disappear.
Now try http://www.drupal.org/admin, you get Access denied but the right hand navs are there.
I chase through the code and found the culprit is menu_get_item() in includes/menu.inc (line 302)
menu_primary_links(), menu_navigation_links() all eventually call menu_get_item(). On a non-exist url like http://www.mysite.com/garbage, menu_get_item() is not aware 'gargabe' is a non-exist path and use that to load menu and the result is nothing.
Well, what to do? One fix is to make menu_get_item() test if the path at hand is a "404" and use '' instead so it just returns menu links as if the path points to the home page.
menu_get_item():
function menu_get_item($path = NULL, $router_item = NULL) {
static $router_items;
if (!isset($path)) {
$path = $_GET['q'];
}
....
Change to:
function menu_get_item($path = NULL, $router_item = NULL) {
static $router_items;
if (!isset($path)) {
$path = $_GET['q'];
}
if (is_path_404($path)) {
$path='';
}
....
Is there a way to figure out we are at a 404 path?
Comments
I believe that nav menu was
I believe that nav menu was removed in a decision to make the page not found pages consume less resources when hit by bots. Create a page then use the 404 page setting in the admin area to direct traffic to that page to get a menu.
Web Developers | Drupal Search Engine | FHQKedUP
But it doesn't really work
That make sense if that's what happen, but it actually goes through the entire chain of action all the way to the database like it normally does except it finds nothing:
menu_primary_links() -> menu_navigation_links() -> menu_tree_page_data() -> menu_get_item()and finally hit the database using the non-exist path, ending up with nothing found. No saving. See includes/menu.inc line 311 to 315 where all the heavy processing is and database query, and it always return at line 328 at the very end.Additionally, with is kind of design choice, there really should be comment stating this fact so late comers can realize what's going on?
I wonder if this is a bug or not.
More information here
I can't find the original developer mailing list on this. But in this thread there is more info on the design decision and possible fixes for overriding the behavior.
http://drupal.org/node/116895
Web Developers | Drupal Search Engine | FHQKedUP
Thans for the pointer to that discussion
I read the discussion there and learned something out of it, especially from the blocks404 module. It turns out by defining a 404 page and point to it using the Error report admin page makes the navigation links show up on 404 page. That's all I needed for my site because I don't have any blocks.
I wanted to see how the 404 page is handled inside Drupal but could not figure out where the call
theme("page", $content)ends up. I expected this to be thetheme_page()function somewhere but couldn't find such. Someone mentioned in the discussion you pointed to that Drupal 6 has notheme_page(). So wheretheme("page", $content)end up calling?