hibernate/hibernate-orm · error · IllegalArgumentException
Function has function kind {}, but other overloads have {}.
Error message
Function has function kind {}, but other overloads have {}. An overloaded function needs a single function kind. What it means
DynamicDispatchFunction requires all overloads of a name to share one FunctionKind (NORMAL, ORDER_BY, AGGREGATE, WINDOW). The constructor compares each overload's getFunctionKind() with the first one seen and throws when they differ, because the SQM -> SQL translator would otherwise not know how to legally place the function in the query.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/DynamicDispatchFunction.java:51
public DynamicDispatchFunction(SqmFunctionRegistry functionRegistry, String... functionNames) {
this.functionRegistry = functionRegistry;
this.functionNames = functionNames;
this.functionKind = functionKind( functionRegistry, functionNames );
}
private static FunctionKind functionKind(SqmFunctionRegistry functionRegistry, String[] functionNames) {
FunctionKind functionKind = null;
// Sanity check
for ( String overload : functionNames ) {
final var functionDescriptor = functionRegistry.findFunctionDescriptor( overload );
if ( functionDescriptor == null ) {
throw new IllegalArgumentException( "No function registered under the name '" + overload + "'" );
}
if ( functionKind == null ) {
functionKind = functionDescriptor.getFunctionKind();
}
else if ( functionKind != functionDescriptor.getFunctionKind() ) {
throw new IllegalArgumentException( "Function has function kind " + functionDescriptor.getFunctionKind()
+ ", but other overloads have " + functionKind
+ ". An overloaded function needs a single function kind." );
}
}
return functionKind;
}
@Override
public FunctionKind getFunctionKind() {
return functionKind;
}
@Override
public <T> SelfRenderingSqmFunction<T> generateSqmExpression(
List<? extends SqmTypedNode<?>> arguments,
ReturnableType<T> impliedResultType,
QueryEngine queryEngine) {
return validateGetFunction( arguments, queryEngine )View on GitHub (pinned to fad1729dce)
Solutions
- Split the overloads by kind: register aggregate/window variants under distinct function names and only group same-kind descriptors in DynamicDispatchFunction
- Check getFunctionKind() of each descriptor you pass; keep FunctionKind uniform across the group
- Upgrade intent: if you need mixed kinds, implement a custom SqmFunctionDescriptor whose generateSqmExpression dispatches per-call instead of relying on DynamicDispatchFunction
Example fix
// before: kinds differ -> IllegalArgumentException at bootstrap
new DynamicDispatchFunction(registry, "myagg_normal", "myagg_aggregate");
// after: same-kind dispatch; aggregate registered separately
new DynamicDispatchFunction(registry, "myagg_int", "myagg_str");
registry.registerFunction("myagg", myAggregateDescriptor); Defensive patterns
Strategy: validation
Validate before calling
FunctionKind kind = descriptors[0].getFunctionKind();
for (SqmFunctionDescriptor d : descriptors) {
if (d.getFunctionKind() != kind) {
throw new IllegalStateException("Mixed FunctionKinds in overload group");
}
} Type guard
boolean sameKind(SqmFunctionDescriptor... ds) {
FunctionKind k = ds[0].getFunctionKind();
return Arrays.stream(ds).allMatch(d -> d.getFunctionKind() == k);
} Prevention
- Group overloads by FunctionKind; keep aggregate/window variants under their own dispatch names
- Review FunctionKind whenever a descriptor is refactored
- Assert kind uniformity in dialect unit tests
When it happens
Trigger: Grouping incompatible descriptors under one dispatch name, e.g. an aggregate descriptor (cast function used with OVER/aggregate semantics) plus a normal SQM function, then registering a DynamicDispatchFunction over both names; happens in custom dialect setup or programmatic registry tweaks.
Common situations: Dialect authors adding an overload that is an aggregate/window variant but forgetting it must be registered under a different name; refactoring function descriptors so a kind changed (e.g. making a function order-by-only) while the dispatch group was not updated.
Related errors
- No function registered under the name '{}'
- Could not instantiate specified Dialect class [<dialectClass
- The function {name} is not an aggregate function
- The function {name} is not an ordered set-aggregate function
- The function {name} is not a window function
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/a3bf36a6b68ffcc9.
Report an issue: GitHub.