apache/beam · error · CannotProvideCoderException

${e}

Error message

${e}

What it means

After confirming the type implements Writable, coderFor() calls WritableCoder.of(rawType). If that call fails with IllegalArgumentException (e.g. the class cannot be instantiated as required by WritableCoder, such as lacking a no-arg constructor), the exception is wrapped in a CannotProvideCoderException with the underlying message as the reason.

Solutions

  1. Add a public no-argument constructor to the Writable class.
  2. Register an explicit Coder for the type rather than using coderFor().
  3. Inspect the wrapped IllegalArgumentException message for the exact rejection reason.

Example fix

// before
public MyWritable(String value) { this.value = value; }
// after
public MyWritable() {} // no-arg ctor for reflection
public MyWritable(String value) { this.value = value; }
Defensive patterns

Strategy: validation

Validate before calling

if (java.lang.reflect.Modifier.isPublic(MyWritable.class.getConstructor().getModifiers()) == false) {
  throw new IllegalStateException("Writable needs a public no-arg constructor");
}

Type guard

static boolean hasNoArgCtor(Class<?> cls) {
  try { cls.getConstructor(); return true; } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
  coder = WritableCoder.of(clazz);
} catch (IllegalArgumentException e) {
  throw new CannotProvideCoderException(e);
}

Prevention

When it happens

Trigger: Calling coderFor() with a Writable subclass that WritableCoder.of() rejects — typically a class without a public no-argument constructor required by Hadoop's ReflectionUtils-based instantiation.

Common situations: Custom Writable classes written with constructor arguments only; anonymous or inner classes without accessible no-arg constructors used as pipeline record types.

Related errors


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

Appendix: source

Thrown at sdks/java/io/hadoop-common/src/main/java/org/apache/beam/sdk/io/hadoop/WritableCoder.java:168

    private static final TypeDescriptor<Writable> WRITABLE_TYPE = new TypeDescriptor<Writable>() {};

    @Override
    public <T> Coder<T> coderFor(
        TypeDescriptor<T> typeDescriptor, List<? extends Coder<?>> componentCoders)
        throws CannotProvideCoderException {
      if (!typeDescriptor.isSubtypeOf(WRITABLE_TYPE)) {
        throw new CannotProvideCoderException(
            String.format(
                "Cannot provide %s because %s does not implement the interface %s",
                WritableCoder.class.getSimpleName(), typeDescriptor, Writable.class.getName()));
      }

      try {
        @SuppressWarnings("unchecked")
        Coder<T> coder = WritableCoder.of((Class) typeDescriptor.getRawType());
        return coder;
      } catch (IllegalArgumentException e) {
        throw new CannotProvideCoderException(e);
      }
    }
  }
}

View on GitHub (pinned to 12126d8942)