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
- Ensure the type in question actually extends com.google.protobuf.Message (use generated proto classes).
- Register the appropriate coder for non-proto types (AvroCoder, SerializableCoder, or a custom CoderProvider).
- If the type wraps a Message, make it a Message subclass or code the wrapper yourself.
- 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
- Only use DynamicProtoCoder for generated protobuf Message types
- Register dedicated coders for POJOs and other non-proto types
- Prefer ProtoCoder.of(MessageClass.class) for explicit proto coding
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
- cannot encode a null ByteString
- coder type must be identical to node type
- GroupByKey requires its input to use KvCoder
- not a float type
- not a signed integer type
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)