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

  1. Split the overloads by kind: register aggregate/window variants under distinct function names and only group same-kind descriptors in DynamicDispatchFunction
  2. Check getFunctionKind() of each descriptor you pass; keep FunctionKind uniform across the group
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/a3bf36a6b68ffcc9. Report an issue: GitHub.