apache/beam · error · IllegalArgumentException
Unable to infer a coder for destination type (inferred from
Error message
Unable to infer a coder for destination type (inferred from .by() as \"" + destinationT + "\") - specify it explicitly using .withDestinationCoder()
What it means
FileIO.Write needs a Coder to serialize each destination object, and the CoderRegistry could not infer one from the type descriptor produced by the .by() destination function. Beam requires an explicit coder when the destination type is not a standard serializable type.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/io/FileIO.java:1564
}
if (getBatchSizeBytes() != null) {
writeFiles = writeFiles.withBatchSizeBytes(getBatchSizeBytes());
}
if (getBatchMaxBufferingDuration() != null) {
writeFiles = writeFiles.withBatchMaxBufferingDuration(getBatchMaxBufferingDuration());
}
return input.apply(writeFiles);
}
private Coder<DestinationT> resolveDestinationCoder(PCollection<UserT> input) {
Coder<DestinationT> destinationCoder = getDestinationCoder();
if (destinationCoder == null) {
TypeDescriptor<DestinationT> destinationT =
TypeDescriptors.outputOf(getDestinationFn().getClosure());
try {
destinationCoder = input.getPipeline().getCoderRegistry().getCoder(destinationT);
} catch (CannotProvideCoderException e) {
throw new IllegalArgumentException(
"Unable to infer a coder for destination type (inferred from .by() as \""
+ destinationT
+ "\") - specify it explicitly using .withDestinationCoder()");
}
}
return destinationCoder;
}
private Collection<PCollectionView<?>> getAllSideInputs() {
return Requirements.union(getDestinationFn(), getOutputFn(), getSinkFn(), getFileNamingFn())
.getSideInputs();
}
private static class ViaFileBasedSink<UserT, DestinationT, OutputT>
extends FileBasedSink<UserT, DestinationT, OutputT> {
private final Write<DestinationT, UserT> spec;
private ViaFileBasedSink(Write<DestinationT, UserT> spec) {View on GitHub (pinned to 12126d8942)
Solutions
- Call .withDestinationCoder(Coder) on the Write transform with a coder for your destination type
- Make the destination type a simple codable type (String, KV, Avro record, etc.) or annotate it with @DefaultCoder
- Register a custom CoderProvider in the CoderRegistry via pipeline options
Example fix
// before
WriteFile<String> write = FileIO.<String>write().by(name -> new MyDest(name)).to(...);
// after
WriteFile<String> write = FileIO.<String>write()
.by(name -> new MyDest(name))
.withDestinationCoder(new MyDestCoder())
.to(...); Defensive patterns
Strategy: validation
Validate before calling
// Verify a coder can be inferred before building the transform
try {
pipeline.getCoderRegistry().getCoder(TypeDescriptor.of(MyDest.class));
} catch (CannotProvideCoderException e) {
throw new IllegalStateException("Register a coder for MyDest via withDestinationCoder", e);
} Type guard
static <T> boolean hasCoder(Pipeline p, TypeDescriptor<T> t) {
try { p.getCoderRegistry().getCoder(t); return true; }
catch (CannotProvideCoderException e) { return false; }
} Try / catch
try {
return pipeline.apply(FileIO.<String>write().by(fn).to(out));
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Unable to infer a coder for destination type")) {
throw new IllegalStateException("Call .withDestinationCoder()", e);
}
throw e;
} Prevention
- Prefer String/KV/Avro destination types that have default coders
- Annotate custom destination classes with @DefaultCoder
- Always pair custom .by() types with .withDestinationCoder()
- Test dynamic-write pipelines with small DirectRunner runs before production
When it happens
Trigger: Calling FileIO.<T>write/writeDynamic().by(fn) where the destination type (DestinationT) is a custom class without a registered coder and without calling .withDestinationCoder() before expansion.
Common situations: Using .by() with a lambda returning a custom POJO or a class lacking a default coder; forgetting withDestinationCoder when switching destination types; Kotlin/Scala data classes without registered coders.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- cannot encode a null Integer
- cannot encode a null Long
- cannot encode a null Short
- cannot encode a null BitSet
- cannot encode a null byte[]
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/62a5c9efb8952c93.
Report an issue: GitHub.