apache/beam · error · IllegalStateException

Subclass of SimpleFunction must override 'apply' method or…

Error message

Subclass of SimpleFunction must override 'apply' method or pass a SerializableFunction to the constructor, usually via a lambda or method reference.

What it means

SimpleFunction is a convenience subclass of DoFn that expects the subclass to override the typed 'apply(InputT)' method (or supply a SerializableFunction via constructor). In its constructor, reflection checks whether 'apply' is still the abstract base method; if so, the subclass is useless and Beam throws IllegalStateException.

Solutions

  1. Override the apply method in the subclass
  2. Pass a lambda/method reference to a MapElements.into(...).via(...) instead of subclassing SimpleFunction
  3. Use the SimpleFunction constructor that accepts a SerializableFunction

Example fix

// before
MapElements<String, Integer> len = MapElements.via(new SimpleFunction<String, Integer>() {});
// after
MapElements<String, Integer> len = MapElements.via(new SimpleFunction<String, Integer>() {
  @Override
  public Integer apply(String s) { return s.length(); }
});
// or simply:
MapElements<String, Integer> len = MapElements.into(TypeDescriptors.integers()).via(String::length);
Defensive patterns

Strategy: type-guard

Validate before calling

// Prefer lambdas: MapElements.into(t).via(MyClass::apply) avoids subclassing entirely

Type guard

boolean isUsableSimpleFunction(SimpleFunction<?,?> f) {
  try { return !SimpleFunction.class.getDeclaredMethod("apply", Object.class).equals(f.getClass().getMethod("apply", Object.class)); }
  catch (NoSuchMethodException e) { return false; }
}

Prevention

When it happens

Trigger: Declaring an anonymous or named subclass of SimpleFunction without overriding apply, e.g. new SimpleFunction<String, Integer>() {} with no body and no SerializableFunction argument.

Common situations: Copy-pasted anonymous class stubs left unimplemented; refactor removed an apply override; IDE-generated anonymous class body left empty; generics erasure confusing the developer into overriding processElement instead of apply.

Understand the failure class

Background: "NotImplementedError: Subclasses should override this method" / "must be implemented" — abstract method errors explained — this error's family across 40 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/SimpleFunction.java:47

@SuppressWarnings({
  "nullness" // TODO(https://github.com/apache/beam/issues/20497)
})
public abstract class SimpleFunction<InputT, OutputT> extends InferableFunction<InputT, OutputT>
    implements SerializableFunction<InputT, OutputT> {

  private final @Nullable SerializableFunction<InputT, OutputT> fn;

  protected SimpleFunction() {
    this.fn = null;
    // A subclass must override apply if using this constructor. Check that via
    // reflection.
    try {
      Method methodThatMustBeOverridden =
          SimpleFunction.class.getDeclaredMethod("apply", Object.class);
      Method methodOnSubclass = getClass().getMethod("apply", Object.class);

      if (methodOnSubclass.equals(methodThatMustBeOverridden)) {
        throw new IllegalStateException(
            "Subclass of SimpleFunction must override 'apply' method"
                + " or pass a SerializableFunction to the constructor,"
                + " usually via a lambda or method reference.");
      }

    } catch (NoSuchMethodException exc) {
      throw new RuntimeException("Impossible state: missing 'apply' method entirely", exc);
    }
  }

  protected SimpleFunction(SerializableFunction<InputT, OutputT> fn) {
    this.fn = fn;
  }

  @Override
  public OutputT apply(InputT input) {
    return fn.apply(input);
  }

View on GitHub (pinned to 12126d8942)