apache/beam · error · java.lang.IllegalArgumentException

DynamicMessage is not supported by the ProtoCoder, use the…

Error message

DynamicMessage is not supported by the ProtoCoder, use the DynamicProtoCoder.

What it means

ProtoCoder requires a concrete protobuf-generated Message class so it can obtain a Parser via getDefaultInstance(). DynamicMessage has no such static factory and needs a Descriptor, so ProtoCoder deliberately rejects it and directs users to DynamicProtoCoder.

Solutions

  1. Use DynamicProtoCoder instead of ProtoCoder for DynamicMessage types.
  2. If the type is known at compile time, use the generated message class with ProtoCoder.of(GeneratedMessage.class).
  3. If relying on automatic coder inference, ensure the PCollection's TypeDescriptor points at the concrete generated class.

Example fix

// before
ProtoCoder<DynamicMessage> coder = ProtoCoder.of(DynamicMessage.class);
// after
DynamicProtoCoder<DynamicMessage> coder = DynamicProtoCoder.of(descriptor);
Defensive patterns

Strategy: type-guard

Validate before calling

if (DynamicMessage.class.equals(type.getRawType())) {
  throw new IllegalArgumentException("use DynamicProtoCoder");
}

Type guard

boolean isDynamic = msg instanceof DynamicMessage; // route to DynamicProtoCoder if true

Try / catch

try { coder = ProtoCoder.of(clazz); } catch (IllegalArgumentException e) { coder = DynamicProtoCoder.of(descriptor); }

Prevention

When it happens

Trigger: Creating ProtoCoder.of(DynamicMessage.class) (or a coderFor/type inference resolving to DynamicMessage) and then decoding, or any path that calls getParser() with protoMessageClass == DynamicMessage.

Common situations: Working with dynamically parsed protos (e.g. from descriptors read at runtime) but picking the wrong coder class; copying coder code from examples that used DynamicMessage with parseFrom.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

   */
  final Set<Class<?>> extensionHostClasses;

  // Transient fields that are lazy initialized and then memoized.
  private transient volatile ExtensionRegistry memoizedExtensionRegistry;
  transient Parser<T> memoizedParser;

  /** Private constructor. */
  protected ProtoCoder(Class<T> protoMessageClass, Set<Class<?>> extensionHostClasses) {
    this.protoMessageClass = protoMessageClass;
    this.extensionHostClasses = extensionHostClasses;
  }

  /** Get the memoized {@link Parser}, possibly initializing it lazily. */
  protected synchronized Parser<T> getParser() {
    if (memoizedParser == null) {
      try {
        if (DynamicMessage.class.equals(protoMessageClass)) {
          throw new IllegalArgumentException(
              "DynamicMessage is not supported by the ProtoCoder, use the DynamicProtoCoder.");
        } else {
          @SuppressWarnings("unchecked")
          T protoMessageInstance =
              (T) protoMessageClass.getMethod("getDefaultInstance").invoke(null);
          @SuppressWarnings("unchecked")
          Parser<T> tParser = (Parser<T>) protoMessageInstance.getParserForType();
          memoizedParser = tParser;
        }
      } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
        throw new IllegalArgumentException(e);
      }
    }
    return memoizedParser;
  }

  /**
   * Returns a {@link CoderProvider} which uses the {@link ProtoCoder} for {@link Message proto

View on GitHub (pinned to 12126d8942)