apache/flink · error · InvalidTypesException
Given class: {} is not a FunctionalInterface. It does not ha
Error message
Given class: {} is not a FunctionalInterface. It does not have any abstract methods. What it means
Thrown by TypeExtractionUtils.getSingleAbstractMethod when the interface is valid (isInterface() == true) but has zero abstract methods. This can happen with a marker interface (e.g. Serializable) or an interface that only contains default and static methods. Without an abstract method, there is no SAM to extract from.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractionUtils.java:257
"Given class: " + baseClass + "is not a FunctionalInterface.");
}
Method sam = null;
for (Method method : baseClass.getMethods()) {
if (Modifier.isAbstract(method.getModifiers())) {
if (sam == null) {
sam = method;
} else {
throw new InvalidTypesException(
"Given class: "
+ baseClass
+ " is not a FunctionalInterface. It has more than one abstract method.");
}
}
}
if (sam == null) {
throw new InvalidTypesException(
"Given class: "
+ baseClass
+ " is not a FunctionalInterface. It does not have any abstract methods.");
}
return sam;
}
/** Returns all declared methods of a class including methods of superclasses. */
public static List<Method> getAllDeclaredMethods(Class<?> clazz) {
List<Method> result = new ArrayList<>();
while (clazz != null) {
Method[] methods = clazz.getDeclaredMethods();
Collections.addAll(result, methods);
clazz = clazz.getSuperclass();
}
return result;
}View on GitHub (pinned to 2f3c205e92)
Solutions
- Ensure the interface has at least one abstract method (the function to implement).
- Implement the correct Flink function interface (MapFunction, FilterFunction, etc.) which has a defined SAM.
- Implement ResultTypeQueryable to provide type information without relying on SAM extraction.
Example fix
// before
public interface MyConfig extends Serializable { // no abstract methods
default int getBatchSize() { return 100; }
}
// after
public class MyMapper implements MapFunction<String, Integer> {
public Integer map(String s) { return s.length(); }
} Defensive patterns
Strategy: type-guard
Validate before calling
long abstractCount = Arrays.stream(baseClass.getMethods())
.filter(m -> Modifier.isAbstract(m.getModifiers()))
.count();
if (abstractCount == 0) {
throw new IllegalArgumentException(
baseClass + " has no abstract methods; cannot extract SAM");
} Type guard
static boolean hasAtLeastOneAbstractMethod(Class<?> clazz) {
if (!clazz.isInterface()) return false;
return Arrays.stream(clazz.getMethods())
.anyMatch(m -> Modifier.isAbstract(m.getModifiers()));
} Prevention
- Ensure function interfaces declare at least one abstract method.
- Do not pass marker interfaces (Serializable, Cloneable) as function base classes.
- Use Flink's built-in function interfaces which all have a well-defined SAM.
When it happens
Trigger: Passing a marker interface (like Serializable or Cloneable) as the baseClass for type extraction. An interface that only contains default methods. An interface where all methods are inherited as defaults from parent interfaces.
Common situations: Custom function base class is accidentally an empty or marker interface. Refactoring removes the abstract method from a previously-valid functional interface but leaves default methods. Using a configuration or options interface instead of a function interface.
Related errors
- Given class: {} is not a FunctionalInterface. It has more th
- Given class: {}is not a FunctionalInterface.
- No lambda method found.
- Could not extract lambda method out of function: {} - {}
- Cannot extract the type argument with index {} because the t
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/aec7299d98636120.
Report an issue: GitHub.