phalcon/cphalcon · error · InvalidArgumentException
The sort callback must be callable or null
Error message
The sort callback must be callable or null
What it means
Support\Collection::sort(var callback = null, int order = 4) accepts null (built-in asort/arsort by order) or a callable passed to uasort. A non-null value that fails is_callable() throws InvalidArgumentException('The sort callback must be callable or null') before any sorting happens.
Source
Thrown at phalcon/Support/Collection.zep:551
/**
* Returns a new collection sorted by value. Keys are preserved. When a
* callback is supplied, `uasort` is used. Without a callback, the
* comparison direction is controlled by the `$order` argument
* (`SORT_ASC` or `SORT_DESC`).
*
* @phpstan-return static<T>
*
* @param callable|null $callback
*/
public function sort(var callback = null, int order = 4) -> <static>
{
var result;
let result = this->data;
if (null !== callback) {
if unlikely true !== is_callable(callback) {
throw new InvalidArgumentException(
"The sort callback must be callable or null"
);
}
uasort(result, callback);
} elseif (order === SORT_DESC) {
arsort(result);
} else {
asort(result);
}
return this->cloneEmpty(result);
}
/**
* Returns the object in an array format
*
* @phpstan-return array<array-key, T>View on GitHub (pinned to b7419de9cd)
Solutions
- Use a closure or canonical array syntax: $collection->sort(fn($a, $b) => $a <=> $b) or $collection->sort([$this, 'compareByName'])
- Validate dynamic callbacks before use: if ($cb !== null && !is_callable($cb)) { throw new InvalidArgumentException(...); }
- After renames, grep for string callback references; ensure the method is accessible (public)
Example fix
// before $collection->sort([$this, 'compareByName']); // method renamed -> not callable // after $collection->sort(fn(array $a, array $b): int => $a['name'] <=> $b['name']);
Defensive patterns
Strategy: type-guard
Validate before calling
if ($callback !== null && !is_callable($callback)) {
throw new InvalidArgumentException('Provided sort callback is not callable');
}
$sorted = $collection->sort($callback); Type guard
function isSortCallback(mixed $callback): bool
{
return $callback === null || is_callable($callback);
} Prevention
- Prefer closures or [$object, 'method'] arrays over string callables
- Validate callback names coming from config or request input with is_callable() before use
- After renaming comparator methods, grep for string references and fix visibility
When it happens
Trigger: A string function name that does not exist (typo like 'strcomp'); wrong method-reference syntax such as $this->compare instead of [$this, 'compare']; 'self::compare' as a plain string where the class is namespaced without a leading backslash; a callback name from config/request input that was never defined; the comparison method was renamed or made private during refactor.
Common situations: Dynamic comparator names driven by configuration; refactors renaming compare methods; closures transported via serialization losing callability; first-class callable syntax confusion producing a string instead of a Closure.
Related errors
- Unable to insert into {table} without data
- The number of values in the update is not the same as fields
- Invalid host {host}
- Invalid HTTP method: {methods}
- Width and height must be specified
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/ca9d6f4a30bd117f.
Report an issue: GitHub.