phalcon/cphalcon · error · InvalidSqlExpressionType

Invalid SQL expression type '{}'

Error message

Invalid SQL expression type '{}'

What it means

The 'type' discriminator of an IR expression node must be one of the values Dialect::getSqlExpression() knows: scalar, object, qualified, literal, placeholder, binary-op, unary-op, parentheses, functionCall, list, all, select, cast, convert, case. Any other string throws InvalidSqlExpressionType with the offending value interpolated into the message. The match is exact and case-sensitive.

Source

Thrown at phalcon/Db/Dialect.zep:426

            case "convert":
                return this->getSqlExpressionConvertValue(
                    expression,
                    escapeChar,
                    bindCounts
                );

            case "case":
                return this->getSqlExpressionCase(
                    expression,
                    escapeChar,
                    bindCounts
                );
        }

        /**
         * Expression type wasn't found
         */
        throw new InvalidSqlExpressionType(type);
    }

    /**
     * Transform an intermediate representation of a schema/table into a
     * database system valid expression
     */
    final public function getSqlTable(var table, string escapeChar = null) -> string
    {
        var tableName, schemaName, aliasName;

        if typeof table == "array" {

            /**
             * The index "0" is the table name
             */
            let tableName = table[0];

            /**

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Use one of the exact (case-sensitive) type strings: scalar, object, qualified, literal, placeholder, binary-op, unary-op, parentheses, functionCall, list, all, select, cast, convert, case.
  2. If a genuinely new node type is needed, override getSqlExpression() in a custom dialect and handle it before delegating to parent.
  3. Regenerate any cached or serialized IR after a Phalcon upgrade.

Example fix

// before
$sql = $dialect->getSqlExpression([
    'type'  => 'binary', // unknown discriminator
    'op'    => '=',
    'left'  => ['type' => 'qualified', 'name' => 'id', 'domain' => 'robots'],
    'right' => ['type' => 'literal', 'value' => '1'],
]);

// after
$sql = $dialect->getSqlExpression([
    'type'  => 'binary-op', // exact discriminator
    'op'    => '=',
    'left'  => ['type' => 'qualified', 'name' => 'id', 'domain' => 'robots'],
    'right' => ['type' => 'literal', 'value' => '1'],
]);
Defensive patterns

Strategy: type-guard

Validate before calling

$known = ['scalar','object','qualified','literal','placeholder','binary-op',
          'unary-op','parentheses','functionCall','list','all','select',
          'cast','convert','case'];
if (!in_array($expression['type'] ?? '', $known, true)) {
    throw new InvalidArgumentException('Unknown IR expression type: ' . ($expression['type'] ?? '(none)'));
}
$sql = $dialect->getSqlExpression($expression);

Type guard

const EXPRESSION_TYPES = ['scalar','object','qualified','literal','placeholder',
    'binary-op','unary-op','parentheses','functionCall','list','all','select',
    'cast','convert','case'];

function isKnownExpressionType(array $node): bool
{
    return in_array($node['type'] ?? '', EXPRESSION_TYPES, true);
}

Prevention

When it happens

Trigger: Passing ['type' => 'binary', ...] where the correct discriminator is 'binary-op'; casing mistakes like 'functioncall' vs 'functionCall'; custom node types from user dialect extensions the base class does not know; serialized/stale IR reused after a Phalcon upgrade renamed discriminators.

Common situations: Hand-built expression arrays; third-party packages feeding custom IR; version drift between Phalcon releases; copy-pasting internal examples with wrong casing.

Related errors


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