apache/beam · error · ValueError
Unexpected mutation
Error message
Unexpected mutation
What it means
WriteToBigTable's process() converts each mutation dict into a form suitable for the BigTable Write API and raises ValueError for mutation types it does not recognize. Only SetCell, DeleteFromColumn, DeleteFromFamily, and DeleteFromRow are accepted.
Source
Thrown at sdks/python/apache_beam/io/gcp/bigtableio.py:325
"column_qualifier": mutation.delete_from_column.column_qualifier
}
time_range = mutation.delete_from_column.time_range
if time_range.start_timestamp_micros:
mutation_dict['start_timestamp_micros'] = struct.pack(
'>q', time_range.start_timestamp_micros)
if time_range.end_timestamp_micros:
mutation_dict['end_timestamp_micros'] = struct.pack(
'>q', time_range.end_timestamp_micros)
elif mutation.__contains__("delete_from_family"):
mutation_dict = {
"type": b'DeleteFromFamily',
"family_name": mutation.delete_from_family.family_name.encode(
'utf-8')
}
elif mutation.__contains__("delete_from_row"):
mutation_dict = {"type": b'DeleteFromRow'}
else:
raise ValueError("Unexpected mutation")
args["mutations"].append(mutation_dict)
yield beam.Row(**args)
class ReadFromBigtable(PTransform):
"""Reads rows from Bigtable.
Returns a PCollection of PartialRowData objects, each representing a
Bigtable row. For more information about this row object, visit
https://cloud.google.com/python/docs/reference/bigtable/latest/row#class-googlecloudbigtablerowpartialrowdatarowkey
"""
URN = "beam:schematransform:org.apache.beam:bigtable_read:v1"
def __init__(self, project_id, instance_id, table_id, expansion_service=None):
"""Initialize a ReadFromBigtable transform.
View on GitHub (pinned to 12126d8942)
Solutions
- Use beam.Row / the documented mutation dict keys exactly: set_cell, delete_from_column, delete_from_family, delete_from_row.
- Validate each mutation dict has one recognized key before writing to the sink.
- Prefer constructing mutations via the documented helpers rather than hand-built dicts.
Example fix
// before
row = {"delete_from_row": True, "unknown_op": 1} # ValueError: Unexpected mutation
// after
row = {"delete_from_row": True} # exactly one recognized mutation key Defensive patterns
Strategy: validation
Validate before calling
VALID = {'set_cell', 'delete_from_column', 'delete_from_family', 'delete_from_row'}
for m in mutations:
if not (set(m.keys()) & VALID):
raise ValueError(f'mutation missing a recognized key: {m.keys()}') Type guard
def is_valid_mutation(m):
return isinstance(m, dict) and bool({'set_cell','delete_from_column','delete_from_family','delete_from_row'} & set(m.keys())) Try / catch
try:
result = pipeline | WriteToBigTable(project_id=..., instance_id=..., table_id=...)
except ValueError as e:
if str(e) == 'Unexpected mutation':
log.error('bad mutation dict in PCollection: check mutation keys')
else:
raise Prevention
- Build mutations with the documented dict keys exactly; never hand-roll alternate key names.
- Unit-test mutation-producing DoFns against the four accepted mutation kinds.
- Validate mutation dicts before sending them into WriteToBigTable.
When it happens
Trigger: A PCollection element's mutation dict lacks any of the recognized keys (set_cell, delete_from_column, delete_from_family, delete_from_row), e.g. a typo like 'DeleteFromRow' vs expected key, or a mutation constructed manually with wrong keys.
Common situations: Building mutations by hand for WriteToBigTable with incorrect key names; passing raw protobuf Mutation objects instead of dicts; Beam version differences in accepted mutation dict key formats.
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
- Unexpected mutation type [%s]: Key value is %s
- Unexpected mutation type [%s]: %s
- MatchContinuously interval must be positive.
- Invalid create disposition %s. Expecting %s
- Invalid write disposition %s. Expecting %s
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/3c10794100168c85.
Report an issue: GitHub.