apache/beam · error · IllegalArgumentException
No method annotated with @%s found in class %s.
Error message
No method annotated with @%s found in class %s.
What it means
ScalarFnReflector.getApplyMethod locates the method annotated with @ScalarFn.ApplyMethod inside a ScalarFn implementation (searching the class and its parents, stopping at ScalarFn itself) so Beam can invoke the UDF. If no method carries the annotation, the ScalarFn is structurally invalid and an IllegalArgumentException is thrown — a ScalarFn must define exactly one apply method.
Source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/ScalarFnReflector.java:43
import org.apache.beam.sdk.util.common.ReflectHelpers;
/** Reflection-based implementation logic for {@link ScalarFn}. */
public class ScalarFnReflector {
/**
* Gets the method annotated with {@link
* org.apache.beam.sdk.extensions.sql.udf.ScalarFn.ApplyMethod} from {@code scalarFn}.
*
* <p>There must be exactly one method annotated with {@link
* org.apache.beam.sdk.extensions.sql.udf.ScalarFn.ApplyMethod}, and it must be public.
*/
public static Method getApplyMethod(ScalarFn scalarFn) {
Class<? extends ScalarFn> clazz = scalarFn.getClass();
Collection<Method> matches =
ReflectHelpers.declaredMethodsWithAnnotation(
ScalarFn.ApplyMethod.class, clazz, ScalarFn.class);
if (matches.isEmpty()) {
throw new IllegalArgumentException(
String.format(
"No method annotated with @%s found in class %s.",
ScalarFn.ApplyMethod.class.getSimpleName(), clazz.getName()));
}
// If we have at least one match, then either it should be the only match
// or it should be an extension of the other matches (which came from parent
// classes).
Method first = matches.iterator().next();
for (Method other : matches) {
if (!first.getName().equals(other.getName())
|| !Arrays.equals(first.getParameterTypes(), other.getParameterTypes())) {
throw new IllegalArgumentException(
String.format(
"Found multiple methods annotated with @%s. [%s] and [%s]",
ScalarFn.ApplyMethod.class.getSimpleName(),
ReflectHelpers.formatMethod(first),
ReflectHelpers.formatMethod(other)));View on GitHub (pinned to 12126d8942)
Solutions
- Annotate exactly one public method with @ScalarFn.ApplyMethod in your ScalarFn subclass.
- Ensure the annotated method lives in the ScalarFn class itself or a superclass of it (not a side helper class).
- Verify you imported org.apache.beam.sdk.schemas.transforms...ScalarFn.ApplyMethod, not a same-named annotation from another library.
- Remove competing annotation uses so exactly one apply method exists (see also the multiple-methods error).
Example fix
// before
public class Upper extends ScalarFn {
public String apply(String s) { return s.toUpperCase(); } // no annotation
}
// after
public class Upper extends ScalarFn {
@ApplyMethod
public String apply(String s) { return s.toUpperCase(); }
} Defensive patterns
Strategy: validation
Validate before calling
static void checkScalarFn(ScalarFn fn) {
long n = java.util.Arrays.stream(fn.getClass().getMethods())
.filter(m -> m.isAnnotationPresent(ScalarFn.ApplyMethod.class)).count();
if (n == 0) throw new IllegalArgumentException(fn.getClass() + " needs an @ApplyMethod");
} Try / catch
try {
ScalarFnReflector.getApplyMethod(scalarFn);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("ScalarFn missing @ApplyMethod: " + scalarFn.getClass().getName(), e);
} Prevention
- Always import the correct ScalarFn.ApplyMethod annotation.
- Add a unit test that calls ScalarFnReflector.getApplyMethod on every ScalarFn.
- Avoid removing annotations during method renames/refactors.
When it happens
Trigger: Passing a ScalarFn subclass that forgot to annotate its apply-style method with @ApplyMethod, or annotated a method in an unrelated helper class, to Beam SQL scalar function registration (ScalarFunctionImpl/create paths).
Common situations: Renaming a method and accidentally removing the annotation; copy-pasting a plain class as a ScalarFn; using a custom annotation instead of ScalarFn.ApplyMethod; defining the function body in a superclass above the ScalarFn boundary.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Found multiple methods annotated with @%s. [%s] and [%s]
- Method %s is not public.
- Cannot create UDF from method: method %s.%s not found
- Failed to create SchemaProvider +providerClass.getSimpleName
- A method marked with SchemaCreate in class {} does not retur
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/2c2da3ace3efc72a.
Report an issue: GitHub.