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
- 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.
- If a genuinely new node type is needed, override getSqlExpression() in a custom dialect and handle it before delegating to parent.
- 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
- Treat IR type strings as an internal enum - copy them exactly, case-sensitively.
- Do not persist serialized IR across Phalcon upgrades.
- Prefer PHQL over hand-built IR; extend the dialect instead of inventing node types.
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
- Invalid SQL expression
- No processor found for the given definition
- The 'dialectClass' '{className}' must implement Phalcon\Db\D
- Savepoints are not supported by this database adapter
- Materialized views are not supported by this dialect
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/e39221d41682d40d.
Report an issue: GitHub.