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

  1. Annotate exactly one public method with @ScalarFn.ApplyMethod in your ScalarFn subclass.
  2. Ensure the annotated method lives in the ScalarFn class itself or a superclass of it (not a side helper class).
  3. Verify you imported org.apache.beam.sdk.schemas.transforms...ScalarFn.ApplyMethod, not a same-named annotation from another library.
  4. 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

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/2c2da3ace3efc72a. Report an issue: GitHub.