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
- Convert Increment/Append logic into Put with values computed client-side.
- Filter or validate RowMutations contents before applying them to the pipeline.
- 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
- Express counter-style updates as read-then-Put instead of Increment.
- Filter generic Mutation collections down to Put/Delete before building RowMutations.
- Add unit tests asserting every Mutation is Put/Delete before encoding.
- Avoid custom Mutation subclasses in Beam pipelines.
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
- 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/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)