apache/beam · error · IllegalArgumentException

Unable to infer coder for output of parseFn (" +…

Error message

Unable to infer coder for output of parseFn (" + TypeDescriptors.outputOf(getParseFn()) + "). Specify it explicitly using withCoder().

What it means

KuduIO Read's coder() needs a Coder for the parseFn output type. If no explicit coder was set via withCoder(), it asks the CoderRegistry to infer one from the parseFn's generic output type; when inference fails (CannotProvideCoderException) it rethrows as this IllegalArgumentException.

Solutions

  1. Call KuduIO.read().withCoder(MyCoder.of()) (or withCoder(CoderRegistry-wide coder)) to supply the coder explicitly
  2. Register a default coder for the output type via CoderRegistry.registerCoderForClass or annotate the type so Beam can infer it
  3. Use a parseFn whose output type is a well-known Beam-supported type (Row, String, etc.) so inference succeeds

Example fix

// before
KuduIO.read().withTable(table).withParseFn(row -> new MyPojo(row));
// after
KuduIO.read().withTable(table).withParseFn(row -> new MyPojo(row))
    .withCoder(SerializableCoder.of(MyPojo.class));
Defensive patterns

Strategy: try-catch

Validate before calling

CoderRegistry registry = pipeline.getCoderRegistry();
try {
  registry.getCoder(TypeDescriptors.outputOf(parseFn));
} catch (CannotProvideCoderException e) {
  // supply withCoder(...) explicitly
}

Try / catch

try {
  Read<T> read = kuduIoRead;
  // expansion resolves coder
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Unable to infer coder for output of parseFn")) {
    read = read.withCoder(SerializableCoder.of(MyPojo.class));
  }
}

Prevention

When it happens

Trigger: Building/serializing a KuduIO read whose parseFn output type is not statically inferable or has no registered default coder (e.g., a custom POJO without @DefaultSchema/registered coder, or a lambda erasing the generic type).

Common situations: Using a parseFn returning a custom class or a generic/lambda-typed result in KuduIO.read(), especially when the pipeline is being expanded and coders must be resolved.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/io/kudu/src/main/java/org/apache/beam/sdk/io/kudu/KuduIO.java:195

      abstract Builder<T> setFaultTolerent(Boolean faultTolerent);

      abstract Builder<T> setParseFn(SerializableFunction<RowResult, T> parseFn);

      abstract Builder<T> setCoder(Coder<T> coder);

      abstract Builder<T> setKuduService(KuduService<T> kuduService);

      abstract Read<T> build();
    }

    @VisibleForTesting
    Coder<T> inferCoder(CoderRegistry coderRegistry) {
      try {
        return getCoder() != null
            ? getCoder()
            : coderRegistry.getCoder(TypeDescriptors.outputOf(getParseFn()));
      } catch (CannotProvideCoderException e) {
        throw new IllegalArgumentException(
            "Unable to infer coder for output of parseFn ("
                + TypeDescriptors.outputOf(getParseFn())
                + "). Specify it explicitly using withCoder().",
            e);
      }
    }

    /** Reads from the Kudu cluster on the specified master addresses. */
    public Read<T> withMasterAddresses(String masterAddresses) {
      checkArgument(masterAddresses != null, "masterAddresses cannot be null or empty");
      return builder().setMasterAddresses(Splitter.on(",").splitToList(masterAddresses)).build();
    }

    /** Reads from the specified table. */
    public Read<T> withTable(String table) {
      checkArgument(table != null, "table cannot be null");
      return builder().setTable(table).build();
    }

View on GitHub (pinned to 12126d8942)