phacility/phabricator · error · Exception
Order vector "%s" is invalid: the last column in an order mu
Error message
Order vector "%s" is invalid: the last column in an order must be a column with unique values, but "%s" is not unique.
What it means
Thrown by setOrderVector() when the LAST column of the order vector is not marked 'unique' => true in getOrderableColumns(). Cursor paging requires a strong (total) ordering — rows must have a fully deterministic sequence — which is only guaranteed if the final sort column has unique values (typically the object 'id'). Without it, paging could skip or repeat rows, so the API refuses the vector.
Source
Thrown at src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php:1072
if (empty($orderable[$key])) {
$valid = implode(', ', array_keys($orderable));
throw new Exception(
pht(
'This query ("%s") does not support sorting by order key "%s". '.
'Supported orders are: %s.',
get_class($this),
$key,
$valid));
}
$unique[$key] = idx($orderable[$key], 'unique', false);
}
// Make sure that the last column is unique so that this is a strong
// ordering which can be used for paging.
$last = last($unique);
if ($last !== true) {
throw new Exception(
pht(
'Order vector "%s" is invalid: the last column in an order must '.
'be a column with unique values, but "%s" is not unique.',
$vector->getAsString(),
last_key($unique)));
}
// Make sure that other columns are not unique; an ordering like "id, name"
// does not make sense because only "id" can ever have an effect.
array_pop($unique);
foreach ($unique as $key => $is_unique) {
if ($is_unique) {
throw new Exception(
pht(
'Order vector "%s" is invalid: only the last column in an order '.
'may be unique, but "%s" is a unique column and not the last '.
'column in the order.',
$vector->getAsString(),View on GitHub (pinned to 5720a38cfe)
Solutions
- Append a unique column (normally 'id') as the final component: setOrderVector(array('title', 'id'))
- If your custom column is genuinely unique (e.g. a unique hash), declare 'unique' => true for it in getOrderableColumns()
Example fix
// before
$query->setOrderVector(array('title'));
// after
$query->setOrderVector(array('title', 'id')); Defensive patterns
Strategy: validation
Validate before calling
// Guarantee a unique terminator before setting the vector.
$orderable = $query->getOrderableColumns();
$last = last($vector);
if (!idx($orderable[$last], 'unique', false)) {
$vector[] = 'id'; // unique on every cursor-paged query
}
$query->setOrderVector($vector); Type guard
function vectorEndsUnique(PhabricatorCursorPagedPolicyAwareQuery $query, array $vector) {
$orderable = $query->getOrderableColumns();
return idx($orderable[last($vector)], 'unique', false) === true;
} Prevention
- End every custom order vector with 'id' (or another column declared 'unique' => true)
- Mark custom columns 'unique' => true in getOrderableColumns() only when values are truly unique
When it happens
Trigger: setOrderVector(array('title')) where title is a non-unique string column; ordering only by a non-unique status/date column; appending a tiebreaker after a unique column is impossible (that is error 1473), so the unique column must come last.
Common situations: Developers sorting by name, priority, or status and forgetting the id tiebreaker; custom orderable columns declared without 'unique' => true used as the final component.
Related errors
- Order vector "%s" is invalid: only the last column in an ord
- This query ("%s") does not support sorting by order key "%s"
- Query "%s" does not support a builtin order "%s". Supported
- Event queries which generate ghost events must include eithe
- Maximum page size for Conduit API method calls is 100, but t
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/adcee070f48bfc16.
Report an issue: GitHub.