I'm trying to essentially create an alias to an entity edit form, but really all I need to do is redirect, but get a Page Not Found error.

function kidb_profile_menu() {

    $items['profile/%uid/edit'] = array(
        'page callback' => 'kidb_profile_redirect_user',
        'page arguments' => array(1),
        'access callback' => array('edit own main_profile profile'),
        'type' => MENU_CALLBACK,

    return $items;

function kidb_profile_redirect_user($uid) {

2 Answers 2


Since you are using the %uid wildcard in the menu definition, your kidb_profile_redirect_user() is not getting a user ID, but what uid_load() would be returning. That function is not defined from any module and that is the reason why you get the "page not found" error.

The list of wildcards defined from Drupal 6 is reported in Wildcard usage and core's wildcards. A description of what auto-loader wildcards are is given in hook_menu():

Wildcards in Paths

Simple Wildcards

Wildcards within paths also work with integer substitution. For example, your module could register path 'my-module/%/edit':

  $items['my-module/%/edit'] = array(
    'page callback' => 'mymodule_abc_edit',
    'page arguments' => array(1),

When path 'my-module/foo/edit' is requested, integer 1 will be replaced with 'foo' and passed to the callback function. Note that wildcards may not be used as the first component.

Auto-Loader Wildcards

Registered paths may also contain special "auto-loader" wildcard components in the form of '%mymodule_abc', where the '%' part means that this path component is a wildcard, and the 'mymodule_abc' part defines the prefix for a load function, which here would be named mymodule_abc_load(). When a matching path is requested, your load function will receive as its first argument the path component in the position of the wildcard; load functions may also be passed additional arguments (see "load arguments" in the return value section below). For example, your module could register path 'my-module/%mymodule_abc/edit':

  $items['my-module/%mymodule_abc/edit'] = array(
    'page callback' => 'mymodule_abc_edit',
    'page arguments' => array(1),

When path 'my-module/123/edit' is requested, your load function mymodule_abc_load() will be invoked with the argument '123', and should load and return an "abc" object with internal id 123:

  function mymodule_abc_load($abc_id) {
    return db_query("SELECT * FROM {mymodule_abc} WHERE abc_id = :abc_id", array(':abc_id' => $abc_id))->fetchObject();

You probably meant to use %user, which would return to your page callback the object returned from user_load(). Using that wildcard avoids you check in your code that the user ID is valid (e.g. there is a user account with that ID), but also means that you should change your code to match the following.

function kidb_profile_redirect_user($account) {
  drupal_goto('profile-main_profile/' . $account->uid . '/edit');
  • 'profile/%user/edit' should be used to have the user_load called Commented Jan 22, 2014 at 12:42
  • Given the details, I think this is more what I'm looking for. Thanks for the help! Commented Jan 22, 2014 at 17:00

When defining your menu path like you did 'profile/%uid/edit', you are using Auto-Loader Wildcards which basically under the hood calls uid_load function.

You should use simple wildcard in your path definition:

$items['profile/%/edit'] = array(
  • Using % would not validate the argument passed to the page callback, which means profile/455555/edit would be valid, even if 455555 is not a valid user ID.
    – avpaderno
    Commented Jan 22, 2014 at 15:19

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.