{"record":{"id":"4a7127dffa336858","repo":"hibernate/hibernate-orm","slug":"the-function-name-is-not-an-aggregate-function","errorCode":null,"errorMessage":"The function {name} is not an aggregate function","messagePattern":"The function (.+?) is not an aggregate function","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/function/AbstractSqmSelfRenderingFunctionDescriptor.java","lineNumber":114,"sourceCode":"\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\targuments,\n\t\t\t\t\t\t\timpliedResultType,\n\t\t\t\t\t\t\tgetArgumentsValidator(),\n\t\t\t\t\t\t\tgetReturnTypeResolver(),\n\t\t\t\t\t\t\tqueryEngine.getCriteriaBuilder(),\n\t\t\t\t\t\t\tgetName()\n\t\t\t\t\t);\n\t\t};\n\t}\n\n\t@Override\n\tpublic <T> SelfRenderingSqmAggregateFunction<T> generateSqmAggregateFunctionExpression(\n\t\t\tList<? extends SqmTypedNode<?>> arguments,\n\t\t\tSqmPredicate filter,\n\t\t\tReturnableType<T> impliedResultType,\n\t\t\tQueryEngine queryEngine) {\n\t\tif ( functionKind != FunctionKind.AGGREGATE ) {\n\t\t\tthrow new UnsupportedOperationException( \"The function \" + getName() + \" is not an aggregate function\" );\n\t\t}\n\t\treturn new SelfRenderingSqmAggregateFunction<>(\n\t\t\t\tthis,\n\t\t\t\tthis,\n\t\t\t\targuments,\n\t\t\t\tfilter,\n\t\t\t\timpliedResultType,\n\t\t\t\tgetArgumentsValidator(),\n\t\t\t\tgetReturnTypeResolver(),\n\t\t\t\tqueryEngine.getCriteriaBuilder(),\n\t\t\t\tgetName()\n\t\t);\n\t}\n\n\t@Override\n\tpublic <T> SelfRenderingSqmOrderedSetAggregateFunction<T> generateSqmOrderedSetAggregateFunctionExpression(\n\t\t\tList<? extends SqmTypedNode<?>> arguments,\n\t\t\tSqmPredicate filter,","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/function/AbstractSqmSelfRenderingFunctionDescriptor.java#L96-L132","documentation":"Every SQM function descriptor carries a FunctionKind (NORMAL, AGGREGATE, ORDERED_SET_AGGREGATE, WINDOW). When the query requests an aggregate-shaped expression — classically a FILTER clause — the engine calls generateSqmAggregateFunctionExpression; if the descriptor's kind is not AGGREGATE it throws UnsupportedOperationException naming the function. Non-aggregate functions cannot take a FILTER clause.","triggerScenarios":"HQL or Criteria using '<nonAggregateFunc>(...) filter (where ...)' — e.g. 'select upper(p.name) filter (where p.active) from Person p'; or a custom function registered without FunctionKind.AGGREGATE (default NORMAL) then used with a filter clause. The exception is raised while building the SQM expression, i.e. at query creation/interpretation time.","commonSituations":"Custom dialect functions registered via NamedSqmFunctionDescriptor / SqmFunctionRegistry without passing FunctionKind.AGGREGATE, then used with FILTER; typos where an aggregate was intended (sum vs concat); expecting a UDAF wrapper to be treated as an aggregate automatically.","solutions":["Use a genuine aggregate function with the FILTER clause (sum, count, avg, min, max, or a registered UDAF).","For your own aggregate function, register the descriptor with FunctionKind.AGGREGATE (constructor argument / registerAlternateKey on a descriptor built with the aggregate kind).","If the filter was meant as a WHERE restriction on a scalar expression, move it into the WHERE clause instead."],"exampleFix":"// before\nList<Long> r = em.createQuery(\"select count(p.id) filter (where p.active) from Person p\", Long.class) // ok\n        .getResultList();\n// but: 'upper(p.name) filter (where p.active)' -> UnsupportedOperationException\n\n// after — custom aggregate registered with the right kind\nqueryEngine.getSqmFunctionRegistry().register(\n    \"my_agg\",\n    new NamedSqmFunctionDescriptor(\"my_agg\", null, null, FunctionKind.AGGREGATE,\n        ArgumentRenderingStrategy.STANDARD, \"my_agg(?1) filter (where ?2)\"));","handlingStrategy":"validation","validationCode":"org.hibernate.query.sqm.function.SqmFunctionDescriptor f =\n    sessionFactory.getQueryEngine().getSqmFunctionRegistry().findFunction(\"my_func\");\nif (f == null || f.getFunctionKind() != org.hibernate.query.sqm.function.FunctionKind.AGGREGATE) {\n    // do not use 'my_func(...) filter (where ...)' — pick a registered aggregate or re-register with FunctionKind.AGGREGATE\n}","typeGuard":null,"tryCatchPattern":"try { em.createQuery(ql, Long.class).getResultList(); } catch (UnsupportedOperationException e) { /* 'not an aggregate function': replace with sum/count/... or register the descriptor with FunctionKind.AGGREGATE */ throw e; }","preventionTips":["When registering custom functions in a dialect, always pass the correct FunctionKind explicitly.","Reserve FILTER clauses for known aggregates; keep scalar expressions out of them.","Cover custom dialect functions with HQL smoke tests at startup."],"tags":["hibernate","hql","sqm","aggregate-function","filter-clause","custom-dialect"],"backgroundTag":"sql-function-kind-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}