I defined the following menu item on my module:

function visita_virtual_menu(){
$items = array();
$items['visita_virtual/marker_selected_handler'] = array(
        'title' => t('Marker Selected Handler'),
        'description' => t('Ajax handler for selected markers'),
        'type' => MENU_CALLBACK,
        'access arguments' => array('access panoramas'),
        'callback' => 'marker_selected_handler');
return $items;


And even created an special permission for my module:

function visita_virtual_permission(){
return array('access panoramas' => array(
        'title' => t('Configurar Panoramas'),
        'description' => t('Configurar la visita virtual'),


Obviously the access panoramas permission appeared on the People Permissions configuration tab on Drupal. I assigned it for anonymous users, logged users, and administrator users (Just for testing purposes).

Now my javascript function does the following:

alert('Callback URL: '+url);

        type : "POST",
        url : url,
        data : {
          'marker_latitude' : location.lat,
          'marker_longitude' : location.lng,
        success : function(data){
            alert('Entro a la funcion success');
        error: function(xmlhttp) {
            alert('An error ocurred: '+xmlhttp.status);

The alert('Callback URL: '+url); line shows the following info:


However I'm always getting 403 access forbidden error. Why?? What I'm doing wrong???

I have been debugging the server's code, and the problem seems to be at this piece of code on menu.inc.

function menu_execute_active_handler($path = NULL, $deliver = TRUE) {
// Check if site is offline.
$page_callback_result = _menu_site_is_offline() ? MENU_SITE_OFFLINE : MENU_SITE_ONLINE;

// Allow other modules to change the site status but not the path because that
// would not change the global variable. hook_url_inbound_alter() can be used
// to change the path. Code later will not use the $read_only_path variable.
$read_only_path = !empty($path) ? $path : $_GET['q'];
drupal_alter('menu_site_status', $page_callback_result, $read_only_path);

// Only continue if the site status is not set.
if ($page_callback_result == MENU_SITE_ONLINE) {
if ($router_item = menu_get_item($path)) {
  if ($router_item['access']) {
    if ($router_item['include_file']) {
      require_once DRUPAL_ROOT . '/' . $router_item['include_file'];
    $page_callback_result = call_user_func_array($router_item['page_callback'],   $router_item['page_arguments']);
  else {
    $page_callback_result = MENU_ACCESS_DENIED;

The $path parameter is getting it's default value. NULL, and then the $read_only_path is obtained from the q $_GET value, for this case the $read_only_path has it's value set on: visita_virtual/marker_selected_handler Is that ok?? shouldn't it be /drupal/visita_virtual/marker_selected_handler?

At this point $router_item = menu_get_item($path) I'm getting a $router_item that has an 'access' value of false. So that's the reason I'm receiving 403. Still I'm lost, I don't know what I'm configuring wrong for the menu...

  • are you logged in as admin ?did Amernath ans worked ? are you still having same problem ? or you found solution ?
    – Hitesh
    May 5, 2014 at 9:43

3 Answers 3


The reason you get an Access denied is because your menu item doesn't have a page callback attribute specified. (You have used callback instead). You can check the documentation of hook_menu() here.

On the same page, you'd notice that it says - when the page callback attribute is omitted for a menu item, the page callback of its parent will be taken.

However, when a parent doesn't exist for the menu item in question, it returns an Access denied. This happens even before the current user's access to your menu item is resolved; so the access callback doesn't really matter. (explains why changing that hasn't helped)


I don't have much experience with Ajax, but try to add to

$items['visita_virtual/marker_selected_handler'] = array(
  // ...
  'access callback' => TRUE,
  • I tried it, however still I'm getting 403 error
    – Pablo
    May 6, 2012 at 14:23

You need to add

'access callback' => 'user_access',

In the menu definition (then disable/enable the module)

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.