apache/beam · error · CannotProvideCoderException

Cannot provide SerializableCoder because {} does not impleme

Error message

Cannot provide SerializableCoder because {} does not implement Serializable

What it means

SerializableCoder's CoderProvider (coderFor) can only supply coders for types implementing java.io.Serializable. When the CoderRegistry falls back to SerializableCoder for a type that isn't Serializable, it throws CannotProvideCoderException with this message. The registry then tries other providers or fails pipeline construction.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/coders/SerializableCoder.java:163

    @Override
    public List<CoderProvider> getCoderProviders() {
      return ImmutableList.of(getCoderProvider());
    }
  }

  /**
   * A {@link CoderProvider} that constructs a {@link SerializableCoder} for any class that
   * implements serializable.
   */
  static class SerializableCoderProvider extends CoderProvider {
    @Override
    public <T> Coder<T> coderFor(
        TypeDescriptor<T> typeDescriptor, List<? extends Coder<?>> componentCoders)
        throws CannotProvideCoderException {
      if (Serializable.class.isAssignableFrom(typeDescriptor.getRawType())) {
        return SerializableCoder.of((TypeDescriptor) typeDescriptor);
      }
      throw new CannotProvideCoderException(
          "Cannot provide SerializableCoder because "
              + typeDescriptor
              + " does not implement Serializable");
    }
  }

  private final Class<T> type;

  /**
   * Access via {@link #getEncodedTypeDescriptor()}.
   *
   * <p>The field is restored lazily if it is not present due to serialization.
   */
  @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
  private transient @Nullable TypeDescriptor<T> typeDescriptor;

  protected SerializableCoder(Class<T> type, TypeDescriptor<T> typeDescriptor) {
    this.type = type;

View on GitHub (pinned to 12126d8942)

Solutions

  1. Make the type implement java.io.Serializable
  2. Register an explicit coder: pipeline.getCoderRegistry().registerCoderForType(descriptor, MyCustomCoder.of(...))
  3. Use AvroCoder, RowCoder, or a schema-based coder instead of SerializableCoder
  4. If it's an immutable value type, implement a custom deterministic Coder<T>

Example fix

// before
class MyKey { String id; } // not Serializable -> CannotProvideCoderException
// after
class MyKey implements Serializable { String id; }
Defensive patterns

Strategy: validation

Validate before calling

if (!Serializable.class.isAssignableFrom(MyKey.class)) { /* register explicit coder or make it Serializable */ }

Type guard

boolean isSerializable(Class<?> c) { return Serializable.class.isAssignableFrom(c); }

Try / catch

try { Coder<T> c = registry.getCoder(TypeDescriptor.of(MyType.class)); } catch (CannotProvideCoderException e) { registry.registerCoderForType(descriptor, myCustomCoder); }

Prevention

When it happens

Trigger: Registering a type for which no other coder provider matches and the raw type does not implement Serializable; using CoderRegistry.getCoder(TypeDescriptor) for a POJO missing `implements Serializable`.

Common situations: POJOs/records used as PCollection elements without Serializable; refactoring a class to drop Serializable; using third-party types as pipeline elements.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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