apache/beam · error · CoderException
Cannot encode a null value.
Error message
Cannot encode a null value.
What it means
KryoCoder.encode() does not support null values; it deliberately throws CoderException("Cannot encode a null value.") before invoking Kryo serialization. Beam coders conventionally reject nulls — nulls must be handled at the PCollection/schema level, not inside the coder.
Solutions
- Filter out null elements before they reach the coder: pipeline.apply(Filter.by(e -> e != null))
- Emit a sentinel/wrapper object (e.g. Optional or a Present/Absent type) instead of null
- Fix the producing DoFn to skip null results rather than returning them
- If nulls are legitimate, wrap in a Nullable-aware container type that Kryo can encode
Example fix
// before return parse(record); // may return null // after MyValue v = parse(record); return v == null ? null : v; // use Filter.by(v -> v != null) downstream, or return Optional-wrapped value
Defensive patterns
Strategy: type-guard
Validate before calling
java pcollection.apply(Filter.by(v -> v != null));
Type guard
java
static <T> boolean isPresent(T v) { return v != null; } Try / catch
java
try {
coder.encode(value, out);
} catch (CoderException e) {
if ("Cannot encode a null value.".equals(e.getMessage())) {
// nulls are unsupported: fix upstream DoFn/filter instead of retrying
}
} Prevention
- Never emit null from DoFns; drop or wrap instead
- Add Filter.by(Objects::nonNull) before Kryo-coded stages
- Use Optional<T> for optional values
- Document coder nullability contract for team pipelines
When it happens
Trigger: Encoding a PCollection element that is null at runtime — e.g. a KV/DoFn emitted null, a parse produced null, or a nullable field feeding a Kryo-coded PCollection.
Common situations: Map/DoFn returning null for filtered records instead of dropping them; JSON/CSV parsing yielding null rows; joins producing null values that flow into the Kryo-coded collection.
Related errors
- cannot encode a null Count-min Sketch
- cannot encode a null T-Digest sketch
- Cannot encode given object of type [<value.getClass()>].
- Class is not registered
- Cannot decode object from input stream.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/18f1e481bd7fce8b.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/extensions/kryo/src/main/java/org/apache/beam/sdk/extensions/kryo/KryoCoder.java:196
/** Unique id of the {@link KryoCoder} instance. */
private final String instanceId = UUID.randomUUID().toString();
/** Options for underlying kryo instance. */
private final SerializableOptions options;
/** Client-defined class registrations to {@link Kryo}. */
private final List<KryoRegistrar> registrars;
private KryoCoder(SerializableOptions options, List<KryoRegistrar> registrars) {
this.options = options;
this.registrars = registrars;
}
@Override
public void encode(T value, OutputStream outStream) throws IOException {
final KryoState kryoState = KryoState.get(this);
if (value == null) {
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);View on GitHub (pinned to 12126d8942)