apache/beam · error · RuntimeException

SolaceIO.Read: Cannot infer a coder for the TypeDescriptor…

Error message

SolaceIO.Read: Cannot infer a coder for the TypeDescriptor. Annotate your output class with @DefaultSchema annotation or create a coder manually and register it in the CoderRegistry.

What it means

SolaceIO.Read must produce a Coder for the user's output type. It first checks the CoderRegistry, then tries to infer a coder from a registered schema (@DefaultSchema); if both fail it throws this RuntimeException. Beam cannot serialize pipeline elements without a coder.

Solutions

  1. Annotate the output class with @DefaultSchema(JavaBeanSchema.class) (or AutoValue/POJO schema).
  2. Register a coder explicitly: pipeline.getCoderRegistry().registerCoderForClass(MyClass.class, new MyClassCoder()).
  3. Ensure the TypeDescriptor passed to withTypeDescriptor matches the class actually output by your mapper.
  4. As a workaround, map to a primitive/serializable type (e.g. String) that has a built-in coder.

Example fix

// before
public class Order { private String id; /* getters/setters */ }
// after
@DefaultSchema(JavaBeanSchema.class)
public class Order { private String id; /* getters/setters */ }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure a coder/schema exists before building the read
// boolean hasSchema = Order.class.isAnnotationPresent(DefaultSchema.class);
// boolean hasCoder = pipeline.getCoderRegistry().getCoder(TypeDescriptor.of(Order.class)) != null;

Type guard

<T> boolean codable(Pipeline p, TypeDescriptor<T> td) {
  try { p.getCoderRegistry().getCoder(td); return true; } catch (CannotProvideCoderException e) { return false; }
}

Try / catch

try { SolaceIO.read()...apply(); }
catch (RuntimeException e) {
  if (e.getMessage().contains("Cannot infer a coder")) registerSchemaOrCoder();
  else throw e;
}

Prevention

When it happens

Trigger: Calling SolaceIO.read() with .withTypeDescriptor(TypeDescriptor.of(SomeClass)) (or a custom mapper returning SomeClass) where SomeClass has no registered coder and is not annotated with @DefaultSchema / has no schema provider in the registry.

Common situations: Using a plain POJO without @DefaultSchema; forgetting to call pipeline.getCoderRegistry().registerCoderForClass or register the Schema; custom mapper output type not matching the annotated type.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/io/solace/src/main/java/org/apache/beam/sdk/io/solace/SolaceIO.java:824

                  configuration.getWatermarkIdleDurationThreshold(),
                  configuration.getParseFn(),
                  configuration.getAckDeadline(),
                  configuration.getNackOnTimeout())));
    }

    @VisibleForTesting
    Coder<T> inferCoder(Pipeline pipeline, TypeDescriptor<T> typeDescriptor) {
      Coder<T> coderFromCoderRegistry = getFromCoderRegistry(pipeline, typeDescriptor);
      if (coderFromCoderRegistry != null) {
        return coderFromCoderRegistry;
      }

      Coder<T> coderFromSchemaRegistry = getFromSchemaRegistry(pipeline, typeDescriptor);
      if (coderFromSchemaRegistry != null) {
        return coderFromSchemaRegistry;
      }

      throw new RuntimeException(
          "SolaceIO.Read: Cannot infer a coder for the TypeDescriptor. Annotate your"
              + " output class with @DefaultSchema annotation or create a coder manually"
              + " and register it in the CoderRegistry.");
    }

    private @Nullable Coder<T> getFromSchemaRegistry(
        Pipeline pipeline, TypeDescriptor<T> typeDescriptor) {
      try {
        return pipeline.getSchemaRegistry().getSchemaCoder(typeDescriptor);
      } catch (NoSuchSchemaException e) {
        return null;
      }
    }

    private @Nullable Coder<T> getFromCoderRegistry(
        Pipeline pipeline, TypeDescriptor<T> typeDescriptor) {
      try {
        return pipeline.getCoderRegistry().getCoder(typeDescriptor);

View on GitHub (pinned to 12126d8942)