{"record":{"id":"20228e7fe7a84084","repo":"apache/flink","slug":"given-class-is-not-a-functionalinterface-it-h","errorCode":null,"errorMessage":"Given class: {} is not a FunctionalInterface. It has more than one abstract method.","messagePattern":"Given class: (.+?) is not a FunctionalInterface\\. It has more than one abstract method\\.","errorType":"exception","errorClass":"InvalidTypesException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractionUtils.java","lineNumber":248,"sourceCode":"     *\n     * @param baseClass a class that is a FunctionalInterface to retrieve a SAM from\n     * @throws InvalidTypesException if the given class does not implement FunctionalInterface\n     * @return single abstract method of the given class\n     */\n    public static Method getSingleAbstractMethod(Class<?> baseClass) {\n\n        if (!baseClass.isInterface()) {\n            throw new InvalidTypesException(\n                    \"Given class: \" + baseClass + \"is not a FunctionalInterface.\");\n        }\n\n        Method sam = null;\n        for (Method method : baseClass.getMethods()) {\n            if (Modifier.isAbstract(method.getModifiers())) {\n                if (sam == null) {\n                    sam = method;\n                } else {\n                    throw new InvalidTypesException(\n                            \"Given class: \"\n                                    + baseClass\n                                    + \" is not a FunctionalInterface. It has more than one abstract method.\");\n                }\n            }\n        }\n\n        if (sam == null) {\n            throw new InvalidTypesException(\n                    \"Given class: \"\n                            + baseClass\n                            + \" is not a FunctionalInterface. It does not have any abstract methods.\");\n        }\n\n        return sam;\n    }\n\n    /** Returns all declared methods of a class including methods of superclasses. */","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractionUtils.java#L230-L266","documentation":"Thrown by TypeExtractionUtils.getSingleAbstractMethod when the interface has more than one abstract method. A functional interface must have exactly one abstract method; having multiple means the JVM cannot determine which method is the 'lambda' target. The method iterates all declared methods and aborts as soon as it finds a second abstract method.","triggerScenarios":"The baseClass interface declares multiple abstract methods (not a valid functional interface). The interface inherits abstract methods from multiple parent interfaces that together total more than one. Default methods are fine, but multiple non-default, non-static abstract methods trigger this.","commonSituations":"Custom function interface that adds a second abstract method beyond the SAM method. Combining multiple Flink interfaces into one custom interface that has overlapping abstract methods. Inheriting from two interfaces that don't share a common abstract method signature.","solutions":["Ensure your function interface has exactly one abstract method (annotate with @FunctionalInterface to get compile-time validation).","Split the interface into separate single-method interfaces.","Implement ResultTypeQueryable on the function class to bypass SAM-based extraction.","Use Flink's built-in function interfaces which are already valid functional interfaces."],"exampleFix":"// before\npublic interface MyFunction<T, O> extends MapFunction<T, O>, FilterFunction<T> {\n    // two abstract methods: map() and filter()\n}\n// after\n// Use MapFunction and FilterFunction as separate operations\nds.map(new MapFunction<String, Integer>() {\n    public Integer map(String s) { return s.length(); }\n})","handlingStrategy":"type-guard","validationCode":"long abstractCount = Arrays.stream(baseClass.getMethods())\n    .filter(m -> Modifier.isAbstract(m.getModifiers()))\n    .count();\nif (abstractCount > 1) {\n    throw new IllegalArgumentException(\n        baseClass + \" has \" + abstractCount + \" abstract methods; expected exactly 1\");\n}","typeGuard":"static boolean hasSingleAbstractMethod(Class<?> clazz) {\n    if (!clazz.isInterface()) return false;\n    long count = Arrays.stream(clazz.getMethods())\n        .filter(m -> Modifier.isAbstract(m.getModifiers())).count();\n    return count == 1;\n}","tryCatchPattern":null,"preventionTips":["Annotate custom function interfaces with @FunctionalInterface — the compiler will reject interfaces with multiple abstract methods.","Avoid mixing multiple Flink function interfaces into a single custom interface.","Use separate function instances for different operations (map vs filter)."],"tags":["type-extraction","functional-interface","lambda","sam"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}