phalcon/cphalcon · error · InvalidSqlExpression

Invalid SQL expression

Error message

Invalid SQL expression

What it means

Phalcon\Db\Dialect::getSqlExpression() compiles intermediate-representation (IR) expression arrays - the nodes the PHQL compiler produces - into SQL. Every node must carry a 'type' discriminator naming its shape ('scalar', 'binary-op', 'functionCall', ...). An array without 'type' cannot be compiled and throws InvalidSqlExpression.

Source

Thrown at phalcon/Db/Dialect.zep:270

         */
        if fetch columnAlias, columnExpression["sqlAlias"] || fetch columnAlias, columnExpression["alias"] {
            return this->prepareColumnAlias(column, columnAlias, escapeChar);
        }

        return this->prepareColumnAlias(column, null, escapeChar);
    }

    /**
     * Transforms an intermediate representation for an expression into a database system valid expression
     */
    public function getSqlExpression( array expression, string escapeChar = null,  array bindCounts = []) -> string
    {
        int i;
        var type, times, postTimes, rawValue, value, nestedDefinition;
        array placeholders;

        if unlikely !fetch type, expression["type"] {
            throw new InvalidSqlExpression();
        }

        switch type {
            /**
             * Resolve scalar column expressions
             */
            case "scalar":
                return this->getSqlExpressionScalar(
                    expression,
                    escapeChar,
                    bindCounts
                );

            /**
             * Resolve object expressions
             */
            case "object":
                return this->getSqlExpressionObject(

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Give the node a valid 'type' key matching one of the cases in Dialect::getSqlExpression().
  2. Prefer Phalcon\Db\RawValue or PHQL itself instead of hand-crafting IR arrays.
  3. If you must build IR, wrap node construction in a helper that always sets 'type' first.

Example fix

// before
$sql = $dialect->getSqlExpression(['value' => 'robots.name']); // throws InvalidSqlExpression

// after
$sql = $dialect->getSqlExpression([
    'type'   => 'qualified',
    'name'   => 'name',
    'domain' => 'robots',
]);
Defensive patterns

Strategy: validation

Validate before calling

if (!isset($expression['type'])) {
    throw new InvalidArgumentException('IR expression node requires a "type" discriminator');
}
$sql = $dialect->getSqlExpression($expression);

Type guard

function isTypedExpressionNode(array $node): bool
{
    return isset($node['type']) && is_string($node['type']);
}

Prevention

When it happens

Trigger: Calling $dialect->getSqlExpression(['value' => 'x']) directly with no 'type' key; hand-built IR fed to the dialect or select builders; nested expression arrays where a sub-node lacks 'type'; middleware that mutates expression arrays and drops the key.

Common situations: Advanced usage extending the dialect or hand-building IR for expressions; debugging PHQL by inspecting and re-feeding compiled arrays; custom query builders that construct nodes without a type-first discipline.

Related errors


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