{"record":{"id":"3aa1dd1888b2fb79","repo":"hibernate/hibernate-orm","slug":"operand-of-op-getoperatorchar-is-of-type","errorCode":null,"errorMessage":"Operand of \" + op.getOperatorChar() + \" is of type '\" + nodeType.getTypeName() + \"' which is not a numeric type (its JDBC type code is not numeric)","messagePattern":"Operand of \" \\+ op\\.getOperatorChar\\(\\) \\+ \" is of type '\" \\+ nodeType\\.getTypeName\\(\\) \\+ \"' which is not a numeric type \\(its JDBC type code is not numeric\\)","errorType":"exception","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java","lineNumber":646,"sourceCode":"\tpublic static void assertDuration(SqmExpression<?> expression) {\n\t\tfinal var nodeType = expression.getNodeType();\n\t\tif ( nodeType != null ) {\n\t\t\tif ( !( nodeType.getSqmType() instanceof JdbcMapping jdbcMapping )\n\t\t\t\t\t|| !jdbcMapping.getJdbcType().isDuration() ) {\n\t\t\t\tthrow new SemanticException(\n\t\t\t\t\t\t\"Operand of 'by' is of type '\" + nodeType.getTypeName() +\n\t\t\t\t\t\t\t\t\"' which is not a duration (its JDBC type code is not duration-like)\"\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static void assertNumeric(SqmExpression<?> expression, UnaryArithmeticOperator op) {\n\t\tfinal var nodeType = expression.getExpressible();\n\t\tif ( nodeType != null ) {\n\t\t\tif ( !( nodeType.getSqmType() instanceof JdbcMapping jdbcMapping )\n\t\t\t\t\t|| !jdbcMapping.getJdbcType().isNumber() ) {\n\t\t\t\tthrow new SemanticException(\n\t\t\t\t\t\t\"Operand of \" + op.getOperatorChar() + \" is of type '\" + nodeType.getTypeName() +\n\t\t\t\t\t\t\t\t\"' which is not a numeric type (its JDBC type code is not numeric)\"\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n","sourceCodeStart":628,"sourceCodeEnd":654,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/TypecheckUtil.java#L628-L654","documentation":"Unary plus/minus in HQL is validated by TypecheckUtil.assertNumeric (SemanticQueryBuilder:3813): the operand's JDBC type must be numeric. Applying `-x` to a String, Boolean, enum, UUID, or date attribute fails this SemanticException during parsing.","triggerScenarios":"`select -e.name from ...`; `order by -e.priority` where priority is an enum; `-e.flag` (Boolean); dynamic sort builders that prepend '-' to invert the ordering of whatever column was chosen.","commonSituations":"Generic ORDER BY helpers that fake descending numeric sort by negating the expression; sign-flipping string-encoded numbers; queries that ran on Hibernate 5 because no unary type check existed.","solutions":["Sort descending with `order by e.x desc` instead of negation","Negate only numeric attributes; cast genuinely numeric strings first: `-cast(e.code as integer)`","In dynamic sort code, verify the attribute type is numeric before emitting a unary '-'"],"exampleFix":"// before (priority is an enum)\norder by -e.priority\n\n// after\norder by e.priority desc","handlingStrategy":"validation","validationCode":"// Dynamic sort inversion: negate only numeric attributes, else use desc\nSingularAttribute<?, ?> attr = mm.entity(Task.class).getSingularAttribute(sortField);\nString order = Number.class.isAssignableFrom(attr.getJavaType())\n    ? \"order by -e.\" + sortField\n    : \"order by e.\" + sortField + \" desc\";","typeGuard":"static boolean isNumericAttr(Attribute<?, ?> a) {\n    return Number.class.isAssignableFrom(a.getJavaType());\n}","tryCatchPattern":"try {\n    return em.createQuery(hql).getResultList();\n} catch (org.hibernate.query.SemanticException e) {\n    throw new QueryBuildException(\"Unary '-' requires a numeric operand: \" + hql, e);\n}","preventionTips":["Prefer `order by x desc` over negation for descending sorts","Check the metamodel JavaType before emitting '-' in generated HQL","Never negate String/Boolean/enum attributes; cast first if content is numeric"],"tags":["hql","unary-operator","type-checking","order-by","hibernate-6"],"backgroundTag":"query-operand-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}