{"record":{"id":"b627b5bb39cf951d","repo":"elastic/elasticsearch","slug":"cannot-use-a-static-method-as-a-function-reference","errorCode":null,"errorMessage":"cannot use a static method as a function reference [%s::%s/%d] with a non-static captured variable","messagePattern":"cannot use a static method as a function reference \\[(.+?)::(.+?)/(.+?)\\] with a non-static captured variable","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/lang-painless/src/main/java/org/elasticsearch/painless/FunctionRef.java","lineNumber":204,"sourceCode":"                        methodName,\n                        captured ? interfaceTypeParametersSize : interfaceTypeParametersSize - 1\n                    );\n\n                    if (painlessMethod == null) {\n                        throw new IllegalArgumentException(\n                            Strings.format(\n                                \"function reference [%s::%s/%d] matching [%s, %s/%d] not found\",\n                                typeName,\n                                methodName,\n                                interfaceTypeParametersSize,\n                                targetClassName,\n                                interfaceMethodName,\n                                interfaceTypeParametersSize\n                            )\n                        );\n                    }\n                } else if (captured) {\n                    throw new IllegalArgumentException(\n                        Strings.format(\n                            \"cannot use a static method as a function reference [%s::%s/%d] with a non-static captured variable\",\n                            typeName,\n                            methodName,\n                            interfaceTypeParametersSize\n                        )\n                    );\n                }\n\n                delegateClassName = painlessMethod.javaMethod().getDeclaringClass().getName();\n                isDelegateInterface = painlessMethod.javaMethod().getDeclaringClass().isInterface();\n                isDelegateAugmented = painlessMethod.javaMethod().getDeclaringClass() != painlessMethod.targetClass();\n\n                if (Modifier.isStatic(painlessMethod.javaMethod().getModifiers())) {\n                    delegateInvokeType = H_INVOKESTATIC;\n                } else if (isDelegateInterface) {\n                    delegateInvokeType = H_INVOKEINTERFACE;\n                } else {","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-painless/src/main/java/org/elasticsearch/painless/FunctionRef.java#L186-L222","documentation":"FunctionRef.create throws this IllegalArgumentException at compile time when a static method is used as a function reference with a non-static captured variable. The compiler first resolves the method as an augmented (instance) method; if that succeeds but the reference also requires capturing an instance (numberOfCaptures == 1), the method is static and cannot accept a receiver capture. Painless rejects this because a static method has no 'this' to bind.","triggerScenarios":"Writing a method reference that captures an instance variable but resolves to a static method: 'String s = 'abc'; Supplier<Integer> len = s::valueOf;' where valueOf is static but the reference tries to capture s as a receiver. The augmented lookup finds the static method, but the capture flag indicates an instance binding is expected.","commonSituations":"Confusion between static and instance method references (e.g. Type::method vs instance::method). Refactoring a method to static without updating the reference syntax. Capturing an instance for a method that is actually static.","solutions":["If the method is static, use the class-qualified form (Type::method) without an instance capture.","If you need an instance binding, ensure the referenced method is an instance (non-static) method.","Rewrite as an explicit lambda to make the binding explicit: '() -> Type.method()' or '() -> instance.method()'."],"exampleFix":"// before\nString s = '42';\nSupplier<Integer> f = s::parseInt;  // parseInt is static\n// after\nSupplier<Integer> f = () -> Integer.parseInt(s);","handlingStrategy":"validation","validationCode":"// Use class-qualified form for static methods; instance form only for instance methods:\n// // Static:  Function<String,Integer> f = Integer::parseInt;\n// // Instance: Function<String,String> f = String::toUpperCase;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not capture an instance for a static method reference.","Use Type::method for static methods, instance::method for instance methods.","Rewrite as a lambda when binding semantics are unclear."],"tags":["painless","elasticsearch","method-reference","static-binding","compile-time"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}