{"record":{"id":"d055b7d215dc6cbd","repo":"phalcon/cphalcon","slug":"invalid-sql-unary-expression","errorCode":null,"errorMessage":"Invalid SQL-unary expression","messagePattern":"Invalid SQL-unary expression","errorType":"exception","errorClass":"InvalidUnaryExpression","httpStatus":null,"severity":"error","filePath":"phalcon/Db/Dialect.zep","lineNumber":1429,"sourceCode":"    final protected function getSqlExpressionUnaryOperations( array expression, string escapeChar = null,  array bindCounts = []) -> string\n    {\n        var left, right;\n\n        /**\n         * Some unary operators use the left operand...\n         */\n        if fetch left, expression[\"left\"] {\n            return this->getSqlExpression(left, escapeChar, bindCounts) . \" \" . expression[\"op\"];\n        }\n\n        /**\n         * ...Others use the right operand\n         */\n        if fetch right, expression[\"right\"] {\n            return expression[\"op\"] . \" \" . this->getSqlExpression(right, escapeChar, bindCounts);\n        }\n\n        throw new InvalidUnaryExpression();\n    }\n\n    /**\n     * Resolve a WHERE clause\n     *\n     * @param array|string expression\n     * @param string|null escapeChar\n     * @param array bindCounts\n     *\n     * @return string\n     */\n    final protected function getSqlExpressionWhere(var expression, string escapeChar = null,  array bindCounts = []) -> string\n    {\n        var whereSql;\n\n        if typeof expression === \"array\" {\n            let whereSql = this->getSqlExpression(expression, escapeChar, bindCounts);\n        } else {","sourceCodeStart":1411,"sourceCodeEnd":1447,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Db/Dialect.zep#L1411-L1447","documentation":"getSqlExpressionUnary() throws InvalidUnaryExpression when a unary-op expression has neither a 'left' nor a 'right' key. The resolver first tries expression['left'] (rendered as 'left OP'), then expression['right'] ('OP right'); if both are absent there is no operand for the operator (NOT, IS NULL, etc.) and the compiler throws.","triggerScenarios":"Passing ['type' => 'unary-op', 'op' => 'NOT'] with no operand; operand stored under a wrong key ('operand', 'value'); nested expression construction that attaches the operand to a copy of the array that is later discarded.","commonSituations":"Building IS NULL / NOT conditions programmatically where the operand branch is skipped for edge cases; copy-pasted expression templates missing the operand key.","solutions":["Attach the operand under 'left' or 'right': ['type' => 'unary-op', 'op' => 'NOT ', 'right' => ['type' => 'qualified', 'name' => 'active']]","For NULL checks prefer Query Builder conditions like where('active IS NULL') which build the unary expression correctly","Validate unary nodes in your expression factory: require isset($node['left']) XOR isset($node['right'])"],"exampleFix":"// before\n$expr = ['type' => 'unary-op', 'op' => 'NOT '];\n\n// after\n$expr = [\n    'type'  => 'unary-op',\n    'op'    => 'NOT ',\n    'right' => ['type' => 'qualified', 'name' => 'active'],\n];","handlingStrategy":"validation","validationCode":"if (($expr['type'] ?? null) === 'unary-op'\n    && !isset($expr['left'])\n    && !isset($expr['right'])\n) {\n    throw new InvalidArgumentException('Unary expression requires a left or right operand');\n}","typeGuard":"function isCompleteUnaryExpression(array $expr): bool\n{\n    return ($expr['type'] ?? null) !== 'unary-op'\n        || isset($expr['left'])\n        || isset($expr['right']);\n}","tryCatchPattern":"try {\n    $sql = $dialect->select($definition);\n} catch (\\Phalcon\\Db\\Exceptions\\InvalidUnaryExpression $e) {\n    throw new InvalidArgumentException('Unary operator without operand', 0, $e);\n}","preventionTips":["Create unary nodes via a helper that always attaches the operand","For IS NULL / NOT conditions use Query Builder where() clauses","Unit-test expression builders for edge cases where operands may be absent"],"tags":["phalcon","sql","dialect","expression-array","unary"],"backgroundTag":"invalid-sql-expression","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}