apache/beam · error · IllegalArgumentException
Unable to infer SQL type from type variable . This usually m
Error message
Unable to infer SQL type from type variable . This usually means you are trying to use a generic type whose type information is not known at runtime. You can wrap your CombineFn into typed subclass by 'new TypedCombineFnDelegate<...>(combineFn) {}' What it means
Beam SQL cannot map a UDAF's input type to a SQL type when the CombineFn's generic type is a TypeVariable (unknown at runtime due to Java type erasure). Calcite needs a concrete RelDataType, and a raw generic CombineFn gives it nothing to infer from. The library throws to force you to supply a typed subclass (TypedCombineFnDelegate) that captures the type parameters in the anonymous class's superclass.
Source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/UdafImpl.java:75
List<FunctionParameter> para = new ArrayList<>();
para.add(
new FunctionParameter() {
@Override
public int getOrdinal() {
return 0; // up to one parameter is supported in UDAF.
}
@Override
public String getName() {
// not used as Beam SQL uses its own execution engine
return null;
}
@Override
public RelDataType getType(RelDataTypeFactory typeFactory) {
Type inputType = getInputType();
if (inputType instanceof TypeVariable) {
throw new IllegalArgumentException(
"Unable to infer SQL type from type variable "
+ inputType
+ ". This usually means you are trying to use a generic type whose type information "
+ "is not known at runtime. You can wrap your CombineFn into typed subclass"
+ " by 'new TypedCombineFnDelegate<...>(combineFn) {}'");
}
return CalciteUtils.sqlTypeWithAutoCast(typeFactory, inputType);
}
@Override
public boolean isOptional() {
// not used as Beam SQL uses its own execution engine
return false;
}
});
return para;
}
View on GitHub (pinned to 12126d8942)
Solutions
- Wrap the CombineFn in a typed anonymous subclass: new TypedCombineFnDelegate<InputT,AccumT,OutputT>(combineFn) {} so the concrete type parameters are preserved in the superclass signature
- Define the CombineFn as a concrete (non-generic) named or anonymous subclass with literal type parameters instead of passing a raw generic instance
- Check the class with clazz.getGenericSuperclass() instanceof ParameterizedType before registering it as a UDAF
Example fix
// before
CombineFn<Long, long[], Long> sumFn = new SumLongFn(); // raw/generic instance
sqlEnv.registerUdaf("SUM_LONG", sumFn);
// after
sqlEnv.registerUdaf("SUM_LONG", new TypedCombineFnDelegate<Long, long[], Long>(sumFn) {}); Defensive patterns
Strategy: type-guard
Validate before calling
java.util.reflect.Type t = getInputType();
if (t instanceof TypeVariable) throw new IllegalArgumentException("Wrap in TypedCombineFnDelegate<...>(fn) {}"); Type guard
static boolean hasConcreteType(CombineFn<?, ?, ?> fn) {
return fn.getClass().getGenericSuperclass() instanceof ParameterizedType
&& Arrays.stream(fn.getClass().getSuperclass().getTypeParameters())
.noneMatch(p -> p instanceof TypeVariable);
} Try / catch
try {
sqlEnv.registerUdaf(name, combineFn);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Unable to infer SQL type")) {
sqlEnv.registerUdaf(name, new TypedCombineFnDelegate<I, A, O>(combineFn) {});
} else throw e;
} Prevention
- Always register CombineFns via TypedCombineFnDelegate<...>(fn) {} or concrete subclasses
- Avoid passing CombineFns created inside generic methods/classes directly to Beam SQL
- Unit-test UDAF registration at startup so erasure failures surface early
When it happens
Trigger: Registering a UDAF via UdfUtils/ReflectiveSchema whose CombineFn is a generic class or was created through a generic method, so getInputType() returns a TypeVariable instead of a concrete Class/ParameterizedType.
Common situations: Defining a CombineFn inside a generic helper method or generic class and passing it to Beam SQL UDAF registration; using a lambda or raw CombineFn reference whose type parameters were erased; registering the same generic CombineFn for multiple SQL types.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot get type arguments for %s: must implement parameteriz
- Subclass of class org.apache.beam.sdk.transforms.CombineFn m
- Could not determine the generic type of the list
- Cannot infer coder for type parameter
- is not a ParameterizedType
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/254bb6537adb3ca6.
Report an issue: GitHub.