Custom module menu item declaration leads to error 404 function eventi_menu() {
  $items = array();
  $items['eventi/book/%/'] = array(
    'title' =&gt; 'Book',
    'page callback' =&gt; 'eventi_book',
    'access arguments' =&gt; array('allow booking'),
    'page arguments' =&gt; array(2),
    'type' =&gt; MENU_CALLBACK
  );
  $items['eventi/book_waits/%/'] = array(
    'title' =&gt; 'Book Waits',
    'page callback' =&gt; 'eventi_book',
    'access arguments' =&gt; array('allow booking'),
    'page arguments' =&gt; array(2),
    'type' =&gt; MENU_CALLBACK
  );
  $items['eventi/unbook/%/'] = array(
    'title' =&gt; 'Unbook',
    'page callback' =&gt; 'eventi_unbook',
    'access arguments' =&gt; array('allow booking'),
    'page arguments' =&gt; array(2),
    'type' =&gt; MENU_CALLBACK
  );

  return $items;
}

function eventi_book($nid) {
  echo 'something';
}


All worked OK, but suddenly, when I visit (for example) http://example.com/eventi/book/201, I get an error 404. I cleared the cache, but I keep to get the same error. Do you have any clue why it happens?
I would guess that trailing slash on the path is throwing you

$items['eventi/book/%'] = array(
  'title' =&gt; 'Book',
  'page callback' =&gt; 'eventi_book',
  'access arguments' =&gt; array('allow booking'),
  'page arguments' =&gt; array(2),
  'type' =&gt; MENU_CALLBACK
);


Also, if you use %node for the variable in the path, the menu router will call node_load() on the given nid from the path and you'll get the full $node object in your callback function, like so:

$items['eventi/book/%node'] = array(
  'title' =&gt; 'Book',
  'page callback' =&gt; 'eventi_book',
  'access arguments' =&gt; array('allow booking'),
  'page arguments' =&gt; array(2),
  'type' =&gt; MENU_CALLBACK
);

// ...and so on, until...

function eventi_book($node) {
   return $node-&gt;title;
}


Also note that your callback function should return a value, not echo it.