phalcon/cphalcon · error · InvalidOrderByExpression

Invalid SQL-ORDER-BY expression

Error message

Invalid SQL-ORDER-BY expression

What it means

getSqlExpressionOrderBy() throws InvalidOrderByExpression when the orderBy definition is an array but one of its elements is not an array. Each element must be a two-part array: [expression, 'ASC'|'DESC'], where the first slot is itself a resolvable expression array. A plain string like 'name DESC' inside the array is rejected at this layer.

Source

Thrown at phalcon/Db/Dialect.zep:1330

     * Resolve an ORDER BY clause
     *
     * @param array|string expression
     * @param string|null escapeChar
     * @param array bindCounts
     *
     * @return string
     */
    final protected function getSqlExpressionOrderBy(var expression, string escapeChar = null,  array bindCounts = []) -> string
    {
        var field, fields, type, fieldSql = null;

        if typeof expression === "array" {
            let fields = [];

            for field in expression {

                if unlikely typeof field != "array" {
                    throw new InvalidOrderByExpression();
                }

                let fieldSql = this->getSqlExpression(
                    field[0],
                    escapeChar,
                    bindCounts
                );

                /**
                 * In the numeric 1 position could be a ASC/DESC clause
                 */
                if fetch type, field[1] && type != "" {
                    let fieldSql .= " " . type;
                }

                let fields[] = fieldSql;
            }

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Convert each entry to [expression, direction] form: [['type' => 'raw', 'value' => 'name'], 'DESC']
  2. Let Phalcon\Db\QueryBuilder->orderBy('name DESC') do the string parsing for you
  3. Sanitize user-supplied sort input into [field, direction] pairs and whitelist the direction

Example fix

// before
$definition['orderBy'] = ['name DESC', 'id'];

// after
$definition['orderBy'] = [
    [['type' => 'raw', 'value' => 'name'], 'DESC'],
    [['type' => 'raw', 'value' => 'id'], 'ASC'],
];
Defensive patterns

Strategy: validation

Validate before calling

foreach ($definition['orderBy'] ?? [] as $entry) {
    if (!is_array($entry)) {
        throw new InvalidArgumentException('Each ORDER BY entry must be [expr, direction]');
    }
}

Type guard

function isOrderByExpressionList(array $orderBy): bool
{
    foreach ($orderBy as $entry) {
        if (!is_array($entry)) {
            return false;
        }
    }
    return true;
}

Try / catch

try {
    $sql = $dialect->select($definition);
} catch (\Phalcon\Db\Exceptions\InvalidOrderByExpression $e) {
    throw new InvalidArgumentException('Malformed ORDER BY definition', 0, $e);
}

Prevention

When it happens

Trigger: Passing definition['orderBy'] = ['name DESC'] or ['id'] (strings) directly to Dialect::select(); mixing string and array entries in the orderBy array. The Query Builder parses orderBy strings into [expr, direction] pairs before reaching the dialect, so this fires mainly on hand-built definitions.

Common situations: Forwarding raw user sort parameters straight into a select() definition; porting SQL ORDER BY clause strings into the array-based API; inconsistent data shape between code paths that build orderBy.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/1b437ff518a633fa. Report an issue: GitHub.