{"record":{"id":"e39221d41682d40d","repo":"phalcon/cphalcon","slug":"invalid-sql-expression-type","errorCode":null,"errorMessage":"Invalid SQL expression type '{}'","messagePattern":"Invalid SQL expression type '(.+?)'","errorType":"exception","errorClass":"InvalidSqlExpressionType","httpStatus":null,"severity":"error","filePath":"phalcon/Db/Dialect.zep","lineNumber":426,"sourceCode":"            case \"convert\":\n                return this->getSqlExpressionConvertValue(\n                    expression,\n                    escapeChar,\n                    bindCounts\n                );\n\n            case \"case\":\n                return this->getSqlExpressionCase(\n                    expression,\n                    escapeChar,\n                    bindCounts\n                );\n        }\n\n        /**\n         * Expression type wasn't found\n         */\n        throw new InvalidSqlExpressionType(type);\n    }\n\n    /**\n     * Transform an intermediate representation of a schema/table into a\n     * database system valid expression\n     */\n    final public function getSqlTable(var table, string escapeChar = null) -> string\n    {\n        var tableName, schemaName, aliasName;\n\n        if typeof table == \"array\" {\n\n            /**\n             * The index \"0\" is the table name\n             */\n            let tableName = table[0];\n\n            /**","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Db/Dialect.zep#L408-L444","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hand-built expression arrays; third-party packages feeding custom IR; version drift between Phalcon releases; copy-pasting internal examples with wrong casing.","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."],"exampleFix":"// before\n$sql = $dialect->getSqlExpression([\n    'type'  => 'binary', // unknown discriminator\n    'op'    => '=',\n    'left'  => ['type' => 'qualified', 'name' => 'id', 'domain' => 'robots'],\n    'right' => ['type' => 'literal', 'value' => '1'],\n]);\n\n// after\n$sql = $dialect->getSqlExpression([\n    'type'  => 'binary-op', // exact discriminator\n    'op'    => '=',\n    'left'  => ['type' => 'qualified', 'name' => 'id', 'domain' => 'robots'],\n    'right' => ['type' => 'literal', 'value' => '1'],\n]);","handlingStrategy":"type-guard","validationCode":"$known = ['scalar','object','qualified','literal','placeholder','binary-op',\n          'unary-op','parentheses','functionCall','list','all','select',\n          'cast','convert','case'];\nif (!in_array($expression['type'] ?? '', $known, true)) {\n    throw new InvalidArgumentException('Unknown IR expression type: ' . ($expression['type'] ?? '(none)'));\n}\n$sql = $dialect->getSqlExpression($expression);","typeGuard":"const EXPRESSION_TYPES = ['scalar','object','qualified','literal','placeholder',\n    'binary-op','unary-op','parentheses','functionCall','list','all','select',\n    'cast','convert','case'];\n\nfunction isKnownExpressionType(array $node): bool\n{\n    return in_array($node['type'] ?? '', EXPRESSION_TYPES, true);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["dialect","phql","expression","invalid-type","internal-api"],"backgroundTag":"invalid-expression-type","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}