apache/beam · error · CoderException
Class is not registered
Error message
Class is not registered
What it means
Kryo with registration required throws IllegalArgumentException("Class is not registered: ...") when it encounters an unregistered class. KryoCoder detects that message prefix and rethrows it as a CoderException so users see the registration problem clearly; any other IllegalArgumentException propagates unchanged.
Solutions
- Register the reported class (from the message text) in your KryoRegistrar / beam KryoOptions registration list
- Register all nested field types, not just the top-level class
- Alternatively disable registrationRequired (kryo.setRegistrationRequired(false)) at the cost of serialization size/performance
- Use kryo.register(Class, Serializer) with a custom serializer for classes you can't modify
Example fix
// before kryo.setRegistrationRequired(true); // MyEvent not registered // after kryo.setRegistrationRequired(true); kryo.register(MyEvent.class); kryo.register(MyEvent.Inner.class);
Defensive patterns
Strategy: validation
Validate before calling
java // before pipeline run kryo.register(MyEvent.class); kryo.register(MyEvent.Inner.class); // register nested types too
Try / catch
java
try {
coder.encode(value, out);
} catch (CoderException e) {
if (e.getMessage().startsWith("Class is not registered")) {
log.severe("Register this class with Kryo: " + e.getMessage());
}
} Prevention
- Maintain a central KryoRegistrar listing all pipeline types
- Re-run registration checks when adding new event/record classes
- Keep registrationRequired=true in CI to surface gaps early
- Watch for renamed generated classes after schema/Avro upgrades
When it happens
Trigger: Kryo instance configured with registrationRequired=true and the pipeline encodes an object whose class (or nested field class) was never registered via a KryoRegistrar / KryoOptions registration list.
Common situations: Adding a new event type to the pipeline without adding it to the Kryo registrations; nested types inside a registered class; lambda/anonymous class fields; upgrade changing generated class names (Avro/protobuf classes).
Related errors
- Cannot encode a null value.
- Cannot encode given object of type [<value.getClass()>].
- Cannot decode object from input stream.
- cannot encode a null Count-min Sketch
- cannot encode a null Integer
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/36f42e272d3049ad.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/extensions/kryo/src/main/java/org/apache/beam/sdk/extensions/kryo/KryoCoder.java:214
throw new CoderException("Cannot encode a null value.");
}
final OutputChunked outputChunked = kryoState.getOutputChunked();
outputChunked.setOutputStream(outStream);
try {
kryoState.getKryo().writeClassAndObject(outputChunked, value);
outputChunked.endChunk();
outputChunked.flush();
} catch (KryoException e) {
outputChunked.reset();
if (e.getCause() instanceof EOFException) {
throw (EOFException) e.getCause();
}
throw new CoderException("Cannot encode given object of type [" + value.getClass() + "].", e);
} catch (IllegalArgumentException e) {
String message = e.getMessage();
if (message != null) {
if (message.startsWith("Class is not registered")) {
throw new CoderException(message);
}
}
throw e;
}
}
@Override
public T decode(InputStream inStream) throws IOException {
final KryoState kryoState = KryoState.get(this);
final InputChunked inputChunked = kryoState.getInputChunked();
inputChunked.setInputStream(inStream);
try {
@SuppressWarnings("unchecked")
final T instance = (T) kryoState.getKryo().readClassAndObject(inputChunked);
return instance;
} catch (KryoException e) {
throw new CoderException("Cannot decode object from input stream.", e);
}View on GitHub (pinned to 12126d8942)