phalcon/cphalcon · error · InvalidGroupByExpression

Invalid SQL-GROUP-BY expression

Error message

Invalid SQL-GROUP-BY expression

What it means

getSqlExpressionGroupBy() throws InvalidGroupByExpression when a GROUP BY definition is an array but one of its elements is not itself an array. Each element must be a structured expression array (e.g. ['type' => 'scalar', ...] or a qualified/raw expression) that getSqlExpression() can resolve; plain string fields are rejected here.

Source

Thrown at phalcon/Db/Dialect.zep:1115

    /**
     * Resolve a GROUP BY clause
     *
     * @param array|string expression
     * @param string|null escapeChar
     * @param array bindCounts
     *
     * @return string
     */
    final protected function getSqlExpressionGroupBy(var expression, string escapeChar = null,  array bindCounts = []) -> string
    {
        var field, fields;

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

            for field in expression {
                if unlikely typeof field != "array" {
                    throw new InvalidGroupByExpression();
                }

                let fields[] = this->getSqlExpression(
                    field,
                    escapeChar,
                    bindCounts
                );
            }

            let fields = join(", ", fields);
        } else {
            let fields = expression;
        }

        return "GROUP BY " . fields;
    }

    /**

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Wrap each field in a scalar/raw expression array: [['type' => 'raw', 'value' => 'type'], ['type' => 'qualified', 'name' => 'r.name', 'domain' => 'r']]
  2. Or build the whole query with Phalcon\Db\QueryBuilder->groupBy(['type']) which performs the wrapping for you
  3. Validate groupBy entries with is_array() before passing them into select()

Example fix

// before
$definition['groupBy'] = ['type', 'r.name'];
$sql = $dialect->select($definition);

// after
$definition['groupBy'] = [
    ['type' => 'raw', 'value' => 'type'],
    ['type' => 'raw', 'value' => 'r.name'],
];
$sql = $dialect->select($definition);
Defensive patterns

Strategy: validation

Validate before calling

foreach ($definition['groupBy'] ?? [] as $field) {
    if (!is_array($field)) {
        throw new InvalidArgumentException('Each GROUP BY entry must be an expression array');
    }
}

Type guard

function isGroupByExpressionList(array $groupBy): bool
{
    foreach ($groupBy as $field) {
        if (!is_array($field)) {
            return false;
        }
    }
    return true;
}

Try / catch

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

Prevention

When it happens

Trigger: Passing definition['groupBy'] = ['type'] or ['r.name'] (list of strings) to Dialect::select(); hand-building a groupBy entry as a string instead of an expression array. Note the Query Builder normally wraps strings into expression arrays, so this bites mostly direct dialect/adapter calls.

Common situations: Writing a custom query compiler that forwards user-supplied group-by fields verbatim; refactoring builder output; assuming strings work because they work in ->orderBy() elsewhere.

Related errors


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