apache/beam · error · IllegalArgumentException
Mutation type cannot be null.
Error message
Mutation type cannot be null.
What it means
In changeMutationInput, each input row's 'type' string selects which Bigtable Mutation to build. Since input.getString("type") can return null when the field is absent, the provider explicitly throws IllegalArgumentException('Mutation type cannot be null.') to fail fast on rows missing this required discriminator.
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigtable/BigtableWriteSchemaTransformProvider.java:264
// convert all row inputs into KV<ByteString, Mutation>
PCollection<KV<ByteString, Mutation>> changedBeamRowMutationsList =
beamRowMutationsList.apply(
MapElements.into(
TypeDescriptors.kvs(
TypeDescriptor.of(ByteString.class), TypeDescriptor.of(Mutation.class)))
.via(
(Row input) -> {
ByteString key =
ByteString.copyFrom(
Preconditions.checkStateNotNull(
input.getBytes("key"),
"Encountered row with null 'key' property."));
Mutation bigtableMutation;
String mutationType =
input.getString("type"); // Direct call, can return null
if (mutationType == null) {
throw new IllegalArgumentException("Mutation type cannot be null.");
}
switch (mutationType) {
case "SetCell":
Mutation.SetCell.Builder setMutation =
Mutation.SetCell.newBuilder()
.setValue(
ByteString.copyFrom(
Preconditions.checkStateNotNull(
input.getBytes("value"),
"Encountered SetCell mutation with null 'value' property.")))
.setColumnQualifier(
ByteString.copyFrom(
Preconditions.checkStateNotNull(
input.getBytes("column_qualifier"),
"Encountered SetCell mutation with null 'column_qualifier' property. ")))
.setFamilyName(
Preconditions.checkStateNotNull(
input.getString("family_name"),View on GitHub (pinned to 12126d8942)
Solutions
- Ensure every input row has a non-null 'type' field with value SetCell, DeleteFamily, DeleteColumn, or DeleteRow
- Add a validation/filter step upstream that drops or repairs rows with null type
- Default the type in your ingestion pipeline where semantically safe (usually SetCell)
Example fix
// before
Row row = Row.withSchema(schema).addValues(keyBytes, null, valueBytes).build();
// after
Row row = Row.withSchema(schema)
.addValues(keyBytes, "SetCell", valueBytes) // type always set
.build(); Defensive patterns
Strategy: type-guard
Validate before calling
if (row.getSchema().hasField("type") && row.getString("type") == null) {
throw new IllegalArgumentException("Row missing mutation type: " + row);
} Type guard
boolean hasMutationType(Row row) {
return row.getSchema().hasField("type") && row.getString("type") != null;
} Try / catch
try {
transform.expand(input);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Mutation type cannot be null")) {
// quarantine the offending rows
}
} Prevention
- Ensure the 'type' column is NOT NULL in source data
- Coerce empty strings/nulls to a default type during ingestion
- Add a Filter.by(r -> r.getString("type") != null) step before the transform
When it happens
Trigger: A Row in the input PCollection lacks the 'type' field or it is null — e.g. rows built with a schema that omits 'type', or data where the type column was never populated.
Common situations: CSV/JSON ingestion where an empty mutation-type column becomes null; partial schema evolution where older records predate the 'type' field.
Related errors
- Inputted Schema caused mutation error, check error logs and
- Unexpected mutation type [%s]: Key value is %s
- Unexpected mutation type [%s]: %s
- Null key
- Null value at column
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/83a6f521191e0d81.
Report an issue: GitHub.