apache/beam · error · IllegalArgumentException
Only Put and Delete are supported
Error message
Only Put and Delete are supported
What it means
HBaseMutationCoder only supports idempotent mutation types: Put and Delete. Increment and Append are non-idempotent and unsafe for distributed retries, so the coder's getType method throws IllegalArgumentException for any other Mutation subclass.
Solutions
- Replace Increment/Append with Put operations (compute the new value client-side) to keep idempotency.
- If Delete/Put only logic is required, filter mutations before writing: only pass instanceof Put or Delete.
- Use a different sink or a custom coder path if you genuinely need Increment/Append semantics.
Example fix
// before list.add(new Increment(row, CF, QUAL, 1L)); // after — read current value, then Put long v = readCurrentValue(row, CF, QUAL); list.add(new Put(row).addColumn(CF, QUAL, Bytes.toBytes(v + 1)));
Defensive patterns
Strategy: type-guard
Validate before calling
public static List<Mutation> onlyIdempotent(List<Mutation> mutations) {
return mutations.stream()
.filter(m -> m instanceof Put || m instanceof Delete)
.collect(Collectors.toList());
} Type guard
static boolean isSupported(Mutation m) {
return m instanceof Put || m instanceof Delete;
} Try / catch
try {
encodeMutation(mutation);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Only Put and Delete")) {
throw new IllegalStateException("Replace Increment/Append with idempotent Put", e);
}
throw e;
} Prevention
- Never put Increment or Append into Beam PCollections meant for HBaseIO.
- Compute values client-side and express updates as Put.
- Add an upstream filter/validation step asserting Put/Delete only.
- Document the idempotency requirement for your pipeline authors.
When it happens
Trigger: Encoding/decoding or coder lookup for a Mutation that is an Increment or Append (or any custom Mutation subclass) inside a pipeline using HBaseMutationCoder — typically writing such mutations with HBaseIO or passing them through Coders.defaultCoder resolution.
Common situations: Using Increment/Append operations in a Beam HBaseIO pipeline; a custom Mutation subclass; library version change introducing new Mutation types.
Related errors
- Only Put and Delete are supported
- Cannot provide because is not a subclass of
- Cannot provide because is not a subclass of
- Mutation type not supported.
- ApproximateUnique.PerKey requires its input to use KvCoder
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/d0fc12b13e9bb066.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/hbase/src/main/java/org/apache/beam/sdk/io/hbase/HBaseMutationCoder.java:69
public void encode(Mutation mutation, OutputStream outStream) throws IOException {
MutationType type = getType(mutation);
MutationProto proto = ProtobufUtil.toMutation(type, mutation);
proto.writeDelimitedTo(outStream);
}
@Override
public Mutation decode(InputStream inStream) throws IOException {
return ProtobufUtil.toMutation(MutationProto.parseDelimitedFrom(inStream));
}
private static MutationType getType(Mutation mutation) {
if (mutation instanceof Put) {
return MutationType.PUT;
} else if (mutation instanceof Delete) {
return MutationType.DELETE;
} else {
// Increment and Append are not idempotent. They should not be used in distributed jobs.
throw new IllegalArgumentException("Only Put and Delete are supported");
}
}
/**
* Returns a {@link CoderProvider} which uses the {@link HBaseMutationCoder} for {@link Mutation
* mutations}.
*/
static CoderProvider getCoderProvider() {
return HBASE_MUTATION_CODER_PROVIDER;
}
private static final CoderProvider HBASE_MUTATION_CODER_PROVIDER =
new HBaseMutationCoderProvider();
/** A {@link CoderProvider} for {@link Mutation mutations}. */
private static class HBaseMutationCoderProvider extends CoderProvider {
@Override
public <T> Coder<T> coderFor(View on GitHub (pinned to 12126d8942)