apache/beam · error · IllegalStateException

Subclass of InferableFunction must override 'apply' method o

Error message

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

What it means

InferableFunction derives type information by reflecting on the subclass's apply(Object) method. If the subclass neither overrides apply nor passes a ProcessFunction/SerializableFunction to the constructor, reflection finds only InferableFunction's own abstract apply, and the constructor throws IllegalStateException because no function body exists to infer types from or invoke.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/InferableFunction.java:52

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

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

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

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

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

  protected InferableFunction(ProcessFunction<InputT, OutputT> fn) {
    this.fn = fn;
  }

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

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass a lambda or method reference to the constructor, e.g. new InferableFunction<InputT, OutputT>(input -> transform(input))
  2. Override apply in the anonymous/derived class: new InferableFunction<InputT, OutputT>() { public OutputT apply(InputT input) {...} }
  3. Prefer the modern replacement: MapElements.via(new SimpleFunction<InputT, OutputT>() {...}) or a lambda with TypeDescriptors
  4. Check the method signature matches exactly apply(Object)-erased, i.e. public OutputT apply(InputT input) with no typos
  5. Catch IllegalStateException at construction time to fail fast with a clearer application-level message

Example fix

// before
new InferableFunction<String, Integer>() { } // no apply override
// after
new InferableFunction<String, Integer>(s -> s.length());
Defensive patterns

Strategy: type-guard

Validate before calling

if (fn.getClass().getMethod("apply", Object.class).getDeclaringClass() == InferableFunction.class) {
  throw new IllegalArgumentException("Pass a lambda or override apply");
}

Type guard

static boolean hasApplyOverride(InferableFunction<?, ?> fn) throws NoSuchMethodException {
  return !fn.getClass()
      .getMethod("apply", Object.class)
      .getDeclaringClass()
      .equals(InferableFunction.class);
}

Try / catch

try {
  InferableFunction<I,O> fn = new InferableFunction<I,O>() { };
} catch (IllegalStateException e) {
  if (e.getMessage().contains("must override 'apply'")) { /* supply lambda/override */ }
  else throw e;
}

Prevention

When it happens

Trigger: new InferableFunction<...>() { } with no apply override and no constructor argument; anonymous subclass that only overrides other methods; calling the no-arg protected constructor path without supplying a function.

Common situations: Migrating old MapElements/Via code that used anonymous InferableFunction subclasses to lambdas; typos where the method is named Apply or has a different signature so it doesn't override apply(Object); copying boilerplate that left the class body empty.

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/10c9949c9949574a. Report an issue: GitHub.