apache/beam · error · IllegalArgumentException
Unknown mutation operation type: %s
Error message
Unknown mutation operation type: %s
What it means
MutationUtils.beamRowToMutationFn() translates the configured mutation operation (INSERT, UPDATE, INSERT_OR_UPDATE, REPLACE, DELETE) into the corresponding Spanner Mutation builder. An operation value outside the known switch cases throws IllegalArgumentException('Unknown mutation operation type: %s').
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/MutationUtils.java:80
* @return function that can convert row to mutation
*/
public static SerializableFunction<Row, Mutation> beamRowToMutationFn(
Mutation.Op operation, String table) {
return row -> {
switch (operation) {
case INSERT:
return MutationUtils.createMutationFromBeamRows(Mutation.newInsertBuilder(table), row);
case DELETE:
return Mutation.delete(table, MutationUtils.createKeyFromBeamRow(row));
case UPDATE:
return MutationUtils.createMutationFromBeamRows(Mutation.newUpdateBuilder(table), row);
case REPLACE:
return MutationUtils.createMutationFromBeamRows(Mutation.newReplaceBuilder(table), row);
case INSERT_OR_UPDATE:
return MutationUtils.createMutationFromBeamRows(
Mutation.newInsertOrUpdateBuilder(table), row);
default:
throw new IllegalArgumentException(
String.format("Unknown mutation operation type: %s", operation));
}
};
}
private static Key createKeyFromBeamRow(Row row) {
Key.Builder builder = Key.newBuilder();
Schema schema = row.getSchema();
List<String> columns = schema.getFieldNames();
columns.forEach(
columnName ->
setBeamValueToKey(builder, schema.getField(columnName).getType(), columnName, row));
return builder.build();
}
public static Mutation createMutationFromBeamRows(
Mutation.WriteBuilder mutationBuilder, Row row) {
Schema schema = row.getSchema();View on GitHub (pinned to 12126d8942)
Solutions
- Set the operation to one of: INSERT, UPDATE, UPSERT (INSERT_OR_UPDATE), REPLACE, DELETE — exact enum name.
- Normalize/trim the operation string before building the transform.
- Check which enum type is expected by the connector version in use (API names changed across versions).
Example fix
// before
SpannerWrite.withMutationOperation("upsert")
// after
SpannerWrite.withMutationOperation("UPSERT") // or INSERT_OR_UPDATE depending on API version Defensive patterns
Strategy: validation
Validate before calling
Set<String> OPS = Set.of("INSERT","UPDATE","UPSERT","REPLACE","DELETE");
if (!OPS.contains(operation.trim().toUpperCase())) throw new IllegalArgumentException("unknown operation: " + operation); Type guard
boolean isKnownOperation(String op) { return java.util.Arrays.stream(MutationOp.values()).anyMatch(m -> m.name().equalsIgnoreCase(op)); } Try / catch
try { rowToMutationFn = MutationUtils.beamRowToMutationFn(table, op); } catch (IllegalArgumentException e) { /* correct the op enum */ } Prevention
- Reference the enum constant (e.g. MutationOp.UPSERT) instead of raw strings
- Normalize casing of operation config at the boundary
- Add a startup-time validation of pipeline options
When it happens
Trigger: Configuring the Spanner write connector with a mutation operation string that is misspelled, lower-cased (e.g. 'insert' vs 'INSERT'), or empty; the enum lookup yields an unexpected value at pipeline construction.
Common situations: Pipeline options/YAML supplying a wrong operation name; upstream refactor renaming the enum; passing a custom string where a MutationOperation enum is expected.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unable to find schema for ${identifier}SchemaTransformProvid
- The specified bucket does not exist: gs://%s
- Unsupported connector ''. Supported connectors are:
- Unknown type {}
- Unknown key part {}
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/0330c8086d029443.
Report an issue: GitHub.