apache/beam · error · IllegalArgumentException

Only Put and Delete are supported

Error message

Only Put and Delete are supported

What it means

Identical to HBaseMutationCoder's check: HBaseRowMutationsCoder.getType maps a Mutation to PUT or DELETE for serialization and throws IllegalArgumentException for anything else, because Increment/Append are non-idempotent and disallowed in distributed jobs.

Solutions

  1. Convert Increment/Append logic into Put with values computed client-side.
  2. Filter or validate RowMutations contents before applying them to the pipeline.
  3. Extend explicitly only with Put/Delete if you control mutation construction.

Example fix

// before
mutations.forEach(m -> rowMutations.add(m)); // may include Increment
// after
mutations.stream()
    .filter(m -> m instanceof Put || m instanceof Delete)
    .forEach(m -> rowMutations.add(m));
Defensive patterns

Strategy: type-guard

Validate before calling

List<Mutation> safe = mutations.stream()
    .peek(m -> { if (!(m instanceof Put) && !(m instanceof Delete))
      throw new IllegalArgumentException("non-idempotent mutation: " + m.getClass()); })
    .collect(Collectors.toList());

Type guard

static boolean isEncodable(Mutation m) {
  return m instanceof Put || m instanceof Delete;
}

Try / catch

try {
  rowMutations.add(mutation);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Only Put and Delete")) {
    // convert Increment to Put before adding
    rowMutations.add(toPut(mutation));
  } else throw e;
}

Prevention

When it happens

Trigger: Serializing (encoding) a RowMutations whose add() received an Increment, Append, or custom Mutation subclass; coder resolution over a PCollection of RowMutations containing such mutations.

Common situations: Counters/atomic increments implemented with Increment inside RowMutations; custom Mutation subclasses; code that generically collects Mutation objects into RowMutations.

Related errors


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

Appendix: source

Thrown at sdks/java/io/hbase/src/main/java/org/apache/beam/sdk/io/hbase/HBaseRowMutationsCoder.java:104

  public List<? extends Coder<?>> getCoderArguments() {
    return Arrays.asList(listCoder, byteArrayCoder);
  }

  /**
   * Coder is always deterministic: 1. {@link RowMutations} maintains equality by row key only,
   * which is asserted equal in this coder 2. Canonical encoding is maintained regardless of object
   * machine or time context
   */
  @Override
  public void verifyDeterministic() {}

  private static MutationType getType(Mutation mutation) {
    if (mutation instanceof Put) {
      return MutationType.PUT;
    } else if (mutation instanceof Delete) {
      return MutationType.DELETE;
    } else {
      throw new IllegalArgumentException("Only Put and Delete are supported");
    }
  }

  /**
   * Returns a {@link CoderProvider} which uses the {@link HBaseRowMutationsCoder} for {@link
   * RowMutations}.
   */
  static CoderProvider getCoderProvider() {
    return HBASE_ROW_MUTATIONS_CODER_PROVIDER;
  }

  private static final CoderProvider HBASE_ROW_MUTATIONS_CODER_PROVIDER =
      new HBaseRowMutationsCoderProvider();

  /** A {@link CoderProvider} for {@link Mutation mutations}. */
  private static class HBaseRowMutationsCoderProvider extends CoderProvider {
    @Override
    public <T> Coder<T> coderFor(

View on GitHub (pinned to 12126d8942)