apache/beam · error · IllegalArgumentException
Mutation type not supported.
Error message
Mutation type not supported.
What it means
HBaseRowMutationsCoder.decode reads each Mutation's serialized type byte and reconstructs Put or Delete objects. A stored type byte that maps to neither PUT nor DELETE indicates a corrupted stream or unsupported type, and decode throws IllegalArgumentException('Mutation type not supported.').
Solutions
- Ensure RowMutations only contain Put/Delete mutations before they are serialized (see getType enforcement).
- Verify all pipeline stages and runners use a consistent Beam version so coder formats match.
- Regenerate any persisted test fixtures/state encoded with an incompatible coder format.
- If you need Increment/Append, restructure to Put-based updates.
Example fix
// before RowMutations rm = new RowMutations(row); rm.add(new Increment(row, CF, QUAL, 1L)); // encoded as unsupported type // after rm.add(new Put(row).addColumn(CF, QUAL, Bytes.toBytes(newValue)));
Defensive patterns
Strategy: validation
Validate before calling
public static void validateRowMutations(RowMutations rm) {
for (Mutation m : rm.getMutations()) {
if (!(m instanceof Put) && !(m instanceof Delete))
throw new IllegalArgumentException("unsupported mutation type in RowMutations: " + m.getClass());
}
} Type guard
static boolean isDecodable(MutationType type) {
return type == MutationType.PUT || type == MutationType.DELETE;
} Try / catch
try {
RowMutations rm = coder.decode(inStream, context);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Mutation type not supported")) {
throw new IOException("corrupt/incompatible RowMutations encoding; regenerate data with same Beam version", e);
}
throw e;
} Prevention
- Keep RowMutations limited to Put/Delete before they enter the pipeline.
- Pin a consistent Beam version across producers and consumers of encoded data.
- Regenerate serialized fixtures when upgrading Beam coder implementations.
- Validate RowMutations contents at construction time, not at decode time.
When it happens
Trigger: Decoding a RowMutations object whose inner mutation has a type byte other than PUT/DELETE — data written by a different/older coder version, corrupted input, or mutations that were Increment/Append smuggled in before serialization elsewhere.
Common situations: Mixing Beam versions where the coder format changed; hand-crafted or corrupted serialized data in state/test fixtures; RowMutations containing Increment/Append built through custom code paths.
Related errors
- Expected 0 or 1, got
- Cannot provide because is not a subclass of
- Cannot provide because is not a subclass of
- Invalid encoded SolrDocument length
- Invalid encoded string length
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/77765c9ba923e8c7.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/hbase/src/main/java/org/apache/beam/sdk/io/hbase/HBaseRowMutationsCoder.java:79
listCoder.encode(value.getMutations(), outStream);
}
@Override
public RowMutations decode(InputStream inStream) throws IOException, IllegalArgumentException {
byte[] rowKey = byteArrayCoder.decode(inStream);
List<Mutation> mutations = listCoder.decode(inStream);
RowMutations rowMutations = new RowMutations(rowKey);
for (Mutation m : mutations) {
MutationType type = getType(m);
if (type == MutationType.PUT) {
rowMutations.add((Put) m);
} else if (type == MutationType.DELETE) {
rowMutations.add((Delete) m);
} else {
throw new IllegalArgumentException("Mutation type not supported.");
}
}
return rowMutations;
}
@Override
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() {}
View on GitHub (pinned to 12126d8942)