{"record":{"id":"c7b3d99758229101","repo":"hibernate/hibernate-orm","slug":"parameter-d-of-function-s-has-type-s-but","errorCode":null,"errorMessage":"Parameter %d of function '%s()' has type '%s', but argument is of type '%s'","messagePattern":"Parameter (.+?) of function '(.+?)\\(\\)' has type '(.+?)', but argument is of type '(.+?)'","errorType":"exception","errorClass":"FunctionArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/function/AvgFunction.java","lineNumber":176,"sourceCode":"\t\t\t\tBindingContext bindingContext) {\n\t\t\tif ( arguments.size() != 1 ) {\n\t\t\t\tthrow new FunctionArgumentException(\n\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\t\"Function %s() has %d parameters, but %d arguments given\",\n\t\t\t\t\t\t\t\tfunctionName,\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\targuments.size()\n\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t\tfinal var expressible = arguments.get( 0 ).getExpressible();\n\t\t\tif ( expressible != null ) {\n\t\t\t\tfinal var domainType = expressible.getSqmType();\n\t\t\t\tif ( domainType != null ) {\n\t\t\t\t\tfinal var jdbcType = getJdbcType( domainType, bindingContext.getTypeConfiguration() );\n\t\t\t\t\tif ( !isNumeric( jdbcType ) ) {\n\t\t\t\t\t\tthrow new FunctionArgumentException(\n\t\t\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\t\t\t\"Parameter %d of function '%s()' has type '%s', but argument is of type '%s'\",\n\t\t\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\t\t\tfunctionName,\n\t\t\t\t\t\t\t\t\t\tNUMERIC,\n\t\t\t\t\t\t\t\t\t\tdomainType.getTypeName()\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate static boolean isNumeric(JdbcType jdbcType) {\n\t\t\tfinal int sqlTypeCode = jdbcType.getDefaultSqlTypeCode();\n\t\t\treturn isNumericType( sqlTypeCode )\n\t\t\t\t|| jdbcType instanceof ArrayJdbcType arrayJdbcType\n\t\t\t\t\t\t&& isNumeric( arrayJdbcType.getElementJdbcType() );","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/function/AvgFunction.java#L158-L194","documentation":"AvgFunction validates that the single argument of avg() resolves to a JDBC type classified as numeric (integer/decimal/float families). A non-numeric domain type such as String, Boolean, or a UUID produces this FunctionArgumentException naming the offending type, because there is no meaningful AVG over it and the SQL would fail anyway.","triggerScenarios":"Queries like 'select avg(e.name) from Employee e', avg() over a String-mapped numeric stored as varchar, avg() over an enum or boolean field; also avg() over a char/enum mapped with @Enumerated where the SqmType is not numeric.","commonSituations":"Legacy schemas storing numbers as varchar/String fields and then used in aggregates; enum ordinals averaged by mistake; upgrading from Hibernate 5 where avg() type-checking was laxer and the query silently produced garbage or DB errors.","solutions":["Apply an explicit cast before averaging: 'select avg(cast(e.amount as double)) ...' when the field is stored as a String","Fix the entity mapping so numeric data uses a numeric Java/JDBC type (Integer/BigDecimal/...)","If the value is genuinely non-numeric, remove avg() and use a different aggregate (min/max/count) or string functions"],"exampleFix":"// before (amount is String)\nDouble a = session.createQuery(\"select avg(e.amount) from Order e\", Double.class).getSingleResult();\n\n// after\nDouble a = session.createQuery(\"select avg(cast(e.amount as double)) from Order e\", Double.class).getSingleResult();","handlingStrategy":"validation","validationCode":"// before executing, confirm the path type is numeric if you build queries dynamically\nSqmExpressible<?> t = ((SqmExpression<?>) arg).getExpressible();\nif (t != null && !t.getSqmType().getTypeName().matches(\"(int|long|float|double|big_decimal).*\")) {\n    throw new IllegalArgumentException(\"avg() needs numeric argument, got \" + t);\n}","typeGuard":"boolean isAvgEligible(Class<?> c) {\n    return Number.class.isAssignableFrom(c)\n        || c == int.class || c == long.class || c == double.class || c == float.class;\n}","tryCatchPattern":"catch (FunctionArgumentException e) {\n    // surface as a user-facing validation error with query context\n    throw new QuerySyntaxException(\"avg() requires a numeric argument\", e);\n}","preventionTips":["Map numeric data with numeric Java types at the entity level","Add an HQL lint pass for avg( over string-typed fields in CI","When ingesting legacy varchar numerics, cast explicitly in the query"],"tags":["hibernate","hql","jpql","avg-function","type-mismatch"],"backgroundTag":"hql-function-argument-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}