apache/beam · error · java.lang.IllegalArgumentException

Unable to register extensions for

Error message

Unable to register extensions for %s

What it means

Thrown by ProtoCoder.validateExtensions when the given extensionHost class does not expose a usable static registerAllExtensions(ExtensionRegistry) method. Protobuf-generated outer classes provide this method to register extension fields; if it is missing or inaccessible, extensions cannot be registered for the coder.

Solutions

  1. Pass the protobuf-generated outer (container) class, not an individual message class.
  2. Regenerate the proto with protoc --java_out so registerAllExtensions is generated.
  3. Check that the protobuf runtime version matches the protoc version used for codegen.
  4. If minified, add a keep rule for registerAllExtensions.

Example fix

// before
ProtoCoder.of(MyOuter.Message.class).withExtensionsFrom(MyOuter.Message.class);
// after
ProtoCoder.of(MyOuter.Message.class).withExtensionsFrom(MyOuter.class);
Defensive patterns

Strategy: validation

Validate before calling

try {
  Method m = extHost.getDeclaredMethod("registerAllExtensions", ExtensionRegistry.class);
  if (!Modifier.isStatic(m.getModifiers())) throw new IllegalArgumentException("not static");
} catch (NoSuchMethodException e) {
  throw new IllegalArgumentException(extHost + " is not a protobuf outer class");
}

Try / catch

try { coder.withExtensionsFrom(host); } catch (IllegalArgumentException e) { log.error("bad extension host: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Calling ProtoCoder.withExtensionsFrom(SomeClass) where SomeClass is not a protobuf-generated outer class, or is a generated class from a protobuf version/toolchain that does not emit registerAllExtensions, or where a SecurityManager blocks reflective access to the method.

Common situations: Passing a Message inner class instead of the generated outer class holding the extensions; mixing protobuf runtime versions so the generated code shape differs; proguard/minification stripping the static method.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/extensions/protobuf/src/main/java/org/apache/beam/sdk/extensions/protobuf/ProtoCoder.java:145

    return of(protoMessageClass);
  }

  /**
   * Validate that all extensionHosts are able to be registered.
   *
   * @param moreExtensionHosts
   */
  void validateExtensions(Iterable<Class<?>> moreExtensionHosts) {
    for (Class<?> extensionHost : moreExtensionHosts) {
      // Attempt to access the required method, to make sure it's present.
      try {
        Method registerAllExtensions =
            extensionHost.getDeclaredMethod("registerAllExtensions", ExtensionRegistry.class);
        checkArgument(
            Modifier.isStatic(registerAllExtensions.getModifiers()),
            "Method registerAllExtensions() must be static");
      } catch (NoSuchMethodException | SecurityException e) {
        throw new IllegalArgumentException(
            String.format("Unable to register extensions for %s", extensionHost.getCanonicalName()),
            e);
      }
    }
  }

  /**
   * Returns a {@link ProtoCoder} like this one, but with the extensions from the given classes
   * registered.
   *
   * <p>Each of the extension host classes must be an class automatically generated by the Protocol
   * Buffers compiler, {@code protoc}, that contains messages.
   *
   * <p>Does not modify this object.
   */
  public ProtoCoder<T> withExtensionsFrom(Iterable<Class<?>> moreExtensionHosts) {
    validateExtensions(moreExtensionHosts);
    return new ProtoCoder<>(

View on GitHub (pinned to 12126d8942)