{"record":{"id":"708b734da89e6c76","repo":"elastic/elasticsearch","slug":"lambda-expects-return-type-but-found-return","errorCode":null,"errorMessage":"lambda expects return type [{}], but found return type [void]","messagePattern":"lambda expects return type \\[(.+?)\\], but found return type \\[void\\]","errorType":"exception","errorClass":"LambdaConversionException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/LambdaBootstrap.java","lineNumber":359,"sourceCode":"\n        endLambdaClass(cw);\n\n        Class<?> lambdaClass = createLambdaClass(loader, cw, lambdaClassType);\n        if (captures.length > 0) {\n            return createCaptureCallSite(lookup, factoryMethodType, lambdaClass);\n        } else {\n            return createNoCaptureCallSite(factoryMethodType, lambdaClass);\n        }\n    }\n\n    /**\n     * Validates some conversions at link time.  Currently, only ensures that the lambda method\n     * with a return value cannot delegate to a delegate method with no return type.\n     */\n    private static void validateTypes(MethodType interfaceMethodType, MethodType delegateMethodType) throws LambdaConversionException {\n\n        if (interfaceMethodType.returnType() != void.class && delegateMethodType.returnType() == void.class) {\n            throw new LambdaConversionException(\n                \"lambda expects return type [\" + interfaceMethodType.returnType() + \"], but found return type [void]\"\n            );\n        }\n    }\n\n    /**\n     * Creates the {@link ClassWriter} to be used for the lambda class generation.\n     */\n    private static ClassWriter beginLambdaClass(String lambdaClassName, Class<?> lambdaInterface) {\n        String baseClass = Type.getInternalName(Object.class);\n        int modifiers = ACC_PUBLIC | ACC_SUPER | ACC_FINAL | ACC_SYNTHETIC;\n\n        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n        cw.visit(CLASS_VERSION, modifiers, lambdaClassName, null, baseClass, new String[] { Type.getInternalName(lambdaInterface) });\n\n        return cw;\n    }\n","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/LambdaBootstrap.java#L341-L377","documentation":"LambdaBootstrap.validateTypes throws this LambdaConversionException at link time when a lambda's functional interface declares a non-void return type but the delegate method (the lambda body or referenced method) returns void. The JVM's lambda metafactory requires that the SAM method and the implementation agree on return type; a value-returning interface cannot delegate to a void method because there would be no value to return. Painless checks this explicitly to give a clear message before the metafactory fails.","triggerScenarios":"Writing a lambda or method reference assigned to a functional interface whose method returns a value, but the body or referenced method returns void: 'Supplier<String> s = () -> { System.out.println('hi'); };' — the lambda body returns nothing but Supplier.get() must return a String.","commonSituations":"Mismatching a lambda body that performs a side effect (no return) with a value-returning functional interface like Function, Supplier, or Predicate. Method references to void-returning methods (e.g. System.out::println) assigned to Function/Supplier types.","solutions":["Ensure the lambda body returns a value matching the interface's return type.","Switch to a void-returning functional interface (e.g. Runnable or Consumer) if the body intentionally has no return value.","If using a method reference, pick a method whose return type matches the interface's SAM return type."],"exampleFix":"// before\nSupplier<String> s = () -> { doc['x'].value; };  // body returns void (statement)\n// after\nSupplier<String> s = () -> doc['x'].value;  // expression returns the value","handlingStrategy":"validation","validationCode":"// Match the lambda body's return type to the interface SAM return type:\n// // Supplier<String> s = () -> 'value';  // returns String, matches Supplier.get()\n// // Runnable r = () -> { println('x'); };  // void body, matches Runnable.run()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure value-returning interfaces (Function, Supplier, Predicate) get a body that returns a value.","Use Runnable or Consumer for void-returning bodies.","Prefer expression lambdas over statement lambdas when a return value is needed."],"tags":["painless","elasticsearch","lambda","return-type","compile-time"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}