{"record":{"id":"826c5124bb0b447e","repo":"apache/beam","slug":"method-s-is-not-public","errorCode":null,"errorMessage":"Method %s is not public.","messagePattern":"Method (.+?) is not public\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/ScalarFnReflector.java","lineNumber":67,"sourceCode":"    // If we have at least one match, then either it should be the only match\n    // or it should be an extension of the other matches (which came from parent\n    // classes).\n    Method first = matches.iterator().next();\n    for (Method other : matches) {\n      if (!first.getName().equals(other.getName())\n          || !Arrays.equals(first.getParameterTypes(), other.getParameterTypes())) {\n        throw new IllegalArgumentException(\n            String.format(\n                \"Found multiple methods annotated with @%s. [%s] and [%s]\",\n                ScalarFn.ApplyMethod.class.getSimpleName(),\n                ReflectHelpers.formatMethod(first),\n                ReflectHelpers.formatMethod(other)));\n      }\n    }\n\n    // Method must be public.\n    if ((first.getModifiers() & Modifier.PUBLIC) == 0) {\n      throw new IllegalArgumentException(\n          String.format(\"Method %s is not public.\", ReflectHelpers.formatMethod(first)));\n    }\n\n    return first;\n  }\n}\n","sourceCodeStart":49,"sourceCodeEnd":74,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/ScalarFnReflector.java#L49-L74","documentation":"The selected @ApplyMethod must be public so Beam can invoke it reflectively across package boundaries. getApplyMethod checks the resolved method's modifiers and throws IllegalArgumentException if it is package-private, protected, or private.","triggerScenarios":"Declaring the @ApplyMethod-annotated method with non-public visibility in a ScalarFn subclass, then registering it as a Beam SQL scalar function.","commonSituations":"IDE-generated apply stubs defaulting to package-private; making the method protected to 'restrict' it; moving the method into an interface-less package-private class during refactoring.","solutions":["Mark the @ApplyMethod method public.","Also ensure the ScalarFn class itself is public so reflection can access the method.","If Java module access is a concern, keep the class public and avoid JPMS strong encapsulation of the package."],"exampleFix":"// before\n@ApplyMethod String apply(String s) { ... }\n// after\n@ApplyMethod public String apply(String s) { ... }","handlingStrategy":"validation","validationCode":"static void checkApplyMethodPublic(ScalarFn fn) throws Exception {\n  java.lang.reflect.Method m = ScalarFnReflector.getApplyMethod(fn);\n  if (!java.lang.reflect.Modifier.isPublic(m.getModifiers()))\n    throw new IllegalStateException(\"@ApplyMethod must be public: \" + m);\n}","typeGuard":null,"tryCatchPattern":"try {\n  ScalarFnReflector.getApplyMethod(scalarFn);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().endsWith(\"is not public.\")) {\n    throw new IllegalStateException(\"Make the @ApplyMethod method public in \" + scalarFn.getClass(), e);\n  }\n  throw e;\n}","preventionTips":["Make both the ScalarFn class and its @ApplyMethod method public.","Review IDE-generated method stubs for default (package-private) visibility.","Add a reflection-based startup check in tests for all registered UDFs."],"tags":["java","reflection","visibility","udf","beam-sql"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}