apache/beam · error · IllegalArgumentException

cannot register Coder : does not have an accessible method n

Error message

cannot register Coder : does not have an accessible method named 'of' with  arguments of Coder type

What it means

CoderProviders.fromStaticMethods requires the Coder class to declare a method named exactly `of` whose parameter count equals the class's type-parameter count and whose parameters are all of type Coder. getDeclaredMethod throws NoSuchMethodException (or SecurityException blocks lookup) when no such method exists, and this IllegalArgumentException is thrown at registration time. Registration fails immediately; the provider is never usable.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderProviders.java:115

      this.factoryMethod = getFactoryMethod(coderClazz);
    }

    /**
     * Returns the static {@code of} constructor method on {@code coderClazz} if it exists. It is
     * assumed to have one {@link Coder} parameter for each type parameter of {@code coderClazz}.
     */
    private static Method getFactoryMethod(Class<?> coderClazz) {
      Method factoryMethodCandidate;

      // Find the static factory method of coderClazz named 'of' with
      // the appropriate number of type parameters.
      int numTypeParameters = coderClazz.getTypeParameters().length;
      Class<?>[] factoryMethodArgTypes = new Class<?>[numTypeParameters];
      Arrays.fill(factoryMethodArgTypes, Coder.class);
      try {
        factoryMethodCandidate = coderClazz.getDeclaredMethod("of", factoryMethodArgTypes);
      } catch (NoSuchMethodException | SecurityException exn) {
        throw new IllegalArgumentException(
            "cannot register Coder "
                + coderClazz
                + ": "
                + "does not have an accessible method named 'of' with "
                + numTypeParameters
                + " arguments of Coder type",
            exn);
      }
      if (!Modifier.isStatic(factoryMethodCandidate.getModifiers())) {
        throw new IllegalArgumentException(
            "cannot register Coder "
                + coderClazz
                + ": "
                + "method named 'of' with "
                + numTypeParameters
                + " arguments of Coder type is not static");
      }
      if (!coderClazz.isAssignableFrom(factoryMethodCandidate.getReturnType())) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Add or rename a static factory in the Coder class: `public static <T> MyCoder<T> of(Coder<T> componentCoder)` with one Coder parameter per type parameter of the class
  2. If the class's `of` signature cannot match, register the coder via CoderProviders.forCoder(typeDescriptor, coderInstance) instead of fromStaticMethods
  3. Ensure the method is declared on coderClazz itself (getDeclaredMethod does not search superclasses)
  4. Check coderClazz.getTypeParameters(): the arity of `of` must equal it exactly
  5. If a SecurityException is the cause, grant reflection permission or run without a restricting SecurityManager

Example fix

// before: no matching factory
class KVCoder<K, V> extends StructuredCoder<KV<K, V>> {
  public static KVCoder of(Coder k, List<Coder> rest) { ... }
}
// after: one Coder arg per type parameter
class KVCoder<K, V> extends StructuredCoder<KV<K, V>> {
  public static <K, V> KVCoder<K, V> of(Coder<K> keyCoder, Coder<V> valueCoder) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasValidOfFactory(Class<?> coderClazz) {
  try {
    Class<?>[] argTypes = new Class<?>[coderClazz.getTypeParameters().length];
    java.util.Arrays.fill(argTypes, Coder.class);
    coderClazz.getDeclaredMethod("of", argTypes);
    return true;
  } catch (NoSuchMethodException | SecurityException e) {
    return false;
  }
}
// assert hasValidOfFactory(MyCoder.class) before CoderProviders.fromStaticMethods(...)

Type guard

static <T extends Coder<?>> boolean canRegisterFromStaticMethods(Class<T> coderClazz) {
  try {
    Class<?>[] argTypes = new Class<?>[coderClazz.getTypeParameters().length];
    java.util.Arrays.fill(argTypes, Coder.class);
    return coderClazz.isAssignableFrom(
        coderClazz.getDeclaredMethod("of", argTypes).getReturnType());
  } catch (NoSuchMethodException | SecurityException e) { return false; }
}

Try / catch

try {
  CoderProvider provider = CoderProviders.fromStaticMethods(rawType, coderClazz);
} catch (IllegalArgumentException e) {
  // registration-time validation failure; fall back to an explicit coder
  provider = CoderProviders.forCoder(typeDescriptor, coderInstance);
}

Prevention

When it happens

Trigger: Passing a coderClazz to CoderProviders.fromStaticMethods(rawType, coderClazz) where the class has no `static Coder<T> of(Coder<?>, ...)` method matching its type-parameter count — e.g. `of` takes different argument types (TypeDescriptor, List<Coder<?>>), the factory is named `of` with wrong arity, or the class relies on a constructor instead of a static factory. Also thrown if a SecurityManager denies access via getDeclaredMethod.

Common situations: Registering a Coder whose factory signature follows an older Beam convention (e.g. of(TypeDescriptor, List)) rather than one Coder arg per type parameter; generic Coder classes with zero type parameters that nonetheless declare of(List<Coder<?>>); running under a SecurityManager or Java module restrictions that block reflection.

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/056964945a568102. Report an issue: GitHub.