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

  1. Call .withDestinationCoder(Coder) on the Write transform with a coder for your destination type
  2. Make the destination type a simple codable type (String, KV, Avro record, etc.) or annotate it with @DefaultCoder
  3. 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

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


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