#autocomplete_path doesn't present a "spinny thing"
What you should do is change $item inside your menu() hook to be

$items['cao_contenttypes/user/autocomplete'] = array(
    'title'            =&gt; 'Autocomplete C&amp;O users',
    'page callback'    =&gt; 'cao_contenttypes_ceao_handler_users_autocomplete',
    'access arguments' =&gt; array('C&amp;O Administrator'),
    'type'             =&gt; MENU_CALLBACK,
);


eg, remove the trailing % (Drupal will add in the string for you just fine when it has one) and then inside your callback do something like this:

function cao_contenttypes_cao_handler_users_autocomplete($str='') {

  $list = array();
  if ($str) {
    // choose users from among a limited subset
    $users = _cao_contenttypes_cao_handler_users();
    array_walk($users, function ($item) use ($str, &amp;$list) {
      $comp = substr($item-&gt;name, 0, strlen($str));
      if ($comp == $str) {
        $list[] = $item-&gt;name;
      }
    });
  }

  drupal_json_output($list);

}


eg, give $str a default value and always return the array of results, even if empty.

Additional comment:  Consider cache()ing the output of _cao_contenttypes_cao_handler_users() if it is a heavyweight function.