apache/beam · warning · CannotProvideCoderException

Cannot provide because is not a subclass of

Error message

Cannot provide %s because %s is not a subclass of %s

What it means

DynamicProtoCoder.coderFor() is a CoderProvider consulted by Beam's coder inference. It only supports types assignable to com.google.protobuf.Message; for any other TypeDescriptor it throws CannotProvideCoderException stating that DynamicProtoCoder cannot provide a coder because the type is not a Message subclass. This is normal provider-decline behavior, but if it is the last applicable provider, coder inference fails for the pipeline.

Solutions

  1. Ensure the type in question actually extends com.google.protobuf.Message (use generated proto classes).
  2. Register the appropriate coder for non-proto types (AvroCoder, SerializableCoder, or a custom CoderProvider).
  3. If the type wraps a Message, make it a Message subclass or code the wrapper yourself.
  4. Use ProtoCoder/ProtoMessageCoder directly for proto types instead of relying on dynamic inference.

Example fix

// before
PCollection<MyPojo> p = ...; // MyPojo is not a Message; inference fails
// after
p.setCoder(AvroCoder.of(MyPojo.class));
Defensive patterns

Strategy: type-guard

Validate before calling

// before requesting a coder for T
typeDescriptor.getRuntimeType().getTypeName(); // confirm it is the generated Message class
boolean ok = com.google.protobuf.Message.class.isAssignableFrom(rawType);

Type guard

static <T> boolean isProtoMessage(TypeDescriptor<T> td) {
  return td.isSubtypeOf(new TypeDescriptor<com.google.protobuf.Message>() {});
}

Try / catch

try {
  registry.getCoder(typeDescriptor);
} catch (CannotProvideCoderException e) {
  // fall back to a non-proto coder for non-Message types
  coder = SerializableCoder.of(rawClass);
}

Prevention

When it happens

Trigger: Coder inference requests a coder for a type T where T is not a subclass of protobuf Message and DynamicProtoCoder.provider() is registered — e.g. a POJO, String, or custom class passed where a proto type is expected.

Common situations: Registering DynamicProtoCoder.provider() globally and then using non-proto types in the same pipeline (harmless unless no other provider matches); accidentally applying a proto coder to a non-proto type after a refactor; mixing generated proto classes with non-Message wrappers.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/extensions/protobuf/src/main/java/org/apache/beam/sdk/extensions/protobuf/DynamicProtoCoder.java:185

   * proto messages}.
   *
   * <p>This method is invoked reflectively from {@link DefaultCoder}.
   */
  public static CoderProvider getCoderProvider() {
    return new ProtoCoderProvider();
  }

  static final TypeDescriptor<Message> MESSAGE_TYPE = new TypeDescriptor<Message>() {};

  /** A {@link CoderProvider} for {@link Message proto messages}. */
  private static class ProtoCoderProvider extends CoderProvider {

    @Override
    public <T> Coder<T> coderFor(
        TypeDescriptor<T> typeDescriptor, List<? extends Coder<?>> componentCoders)
        throws CannotProvideCoderException {
      if (!typeDescriptor.isSubtypeOf(MESSAGE_TYPE)) {
        throw new CannotProvideCoderException(
            String.format(
                "Cannot provide %s because %s is not a subclass of %s",
                DynamicProtoCoder.class.getSimpleName(), typeDescriptor, Message.class.getName()));
      }

      @SuppressWarnings("unchecked")
      TypeDescriptor<? extends Message> messageType =
          (TypeDescriptor<? extends Message>) typeDescriptor;
      try {
        @SuppressWarnings("unchecked")
        Coder<T> coder = (Coder<T>) DynamicProtoCoder.of(messageType);
        return coder;
      } catch (IllegalArgumentException e) {
        throw new CannotProvideCoderException(e);
      }
    }
  }
}

View on GitHub (pinned to 12126d8942)