It's definitely your custom route, could you please try yoursite.com/user/id/?page=2 cause I think that the string id?page=2 gets passed as one parameter.
You can also do debugging with printing out the array of passed url keys:
echo '<pre>';
print_r($this->uri->segment_array());
echo '</pre>'
and you will get all params passed to your controller action. You can also see this answer: Handling question mark in url in codeigniter about extending the core URI class if that is needed.
I hope this helps, otherwise more info will be helpful, for example what are the url keys passed in your controller when you are using normal request like site.com/user/id and when you are doing site.com/user/id?page=2 requests.
****** EDIT **********
If you are using CI 1.7.1 or 1.7.2 then you are getting [1] => page because in the _fetch_uri_string method you have something like this:
if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
{
$this->uri_string = key($_GET);
return;
}
Since you have site.com/user/id/?page=2 this means: $_GET['page'] = 2 and page is the name of the key in $_GET
Please use the link above about how to extend this class in your application and add your own logic here, for example something like this would work for 1.7.1 or 1.7.2
if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
{
//Comment this line cause you don't need it
//$this->uri_string = key($_GET);
//fetch the current page number if there is one
$page_number = (int) $_GET['page'];
//Set the uri_string here with the proper id and pass the id (which you should get here too) and the page number as second parameter then just return; to stop execution further
$this->uri_string = 'dashboard/index/id/'.$page_number
return;
}
//In your dashboard controller:
//Set default values to 0 and process further
public function index($id=0, $page_number=0)
{
}
Hope this helps