apache/beam · error · ValueError
No or more than one write mutation operation provided: <
Error message
No or more than one write mutation operation provided: <%s: %s>
What it means
WriteMutation is a wrapper for exactly one Spanner write mutation (insert, update, insert_or_update, replace, or delete). Its constructor raises this ValueError if zero or more than one of these mutation collections is provided, because a mutation must represent a single operation kind.
Solutions
- Ensure exactly one of insert/update/insert_or_update/replace/delete is non-None in the constructor call.
- If the operation is dynamic, compute the correct WriteMutation class method before constructing.
- Wrap multiple operations in a MutationGroup with separate WriteMutation instances instead.
Example fix
# before WriteMutation.insert(table, entities, delete=delete_ops) # after WriteMutation.insert(table, entities)
Defensive patterns
Strategy: validation
Validate before calling
def make_write_mutation(operation, table, rows):
factories = {'insert': 'insert', 'update': 'update',
'insert_or_update': 'insert_or_update',
'replace': 'replace', 'delete': 'delete'}
assert operation in factories and operation is not None
return getattr(WriteMutation, factories[operation])(table, rows) Try / catch
try:
mutation = WriteMutation.insert(t, rows, **extra)
except ValueError as e:
logging.error('WriteMutation must wrap exactly one operation: %s', e)
raise Prevention
- Pass only one mutation kind per WriteMutation call
- Use factory methods (insert/update/delete/...) rather than raw constructor kwargs
- Combine multiple operations with MutationGroup of separate WriteMutation objects
When it happens
Trigger: Calling WriteMutation.insert(...) plus another setter like WriteMutation.delete(...) in the same constructor; or creating a WriteMutation with all-None mutation args (e.g. WriteMutation() with keyword args that resolve to None).
Common situations: Programmatically building mutations where several candidate mutation lists default to non-None empty values or where a variable may be None and more than one gets passed; typos passing two operation kinds at once.
Related errors
- Invalid object type: . Object must be an instance of…
- Read operation in the constructor only works with the root…
- Spanner required read operation, sql or table with columns.
- Unknown operation action
- Basepath %r must be GCS path.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/3d29f8626e884951.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/io/gcp/experimental/spannerio.py:999
lists is equivalent to sending multiple Mutations, each containing one
`values` entry and repeating table and columns.
keyset: (Optional) The primary keys of the rows within table to delete.
Delete is idempotent. The transaction will succeed even if some or
all rows do not exist.
"""
self._columns = columns
self._values = values
self._keyset = keyset
self._insert = insert
self._update = update
self._insert_or_update = insert_or_update
self._replace = replace
self._delete = delete
if sum([1 for x in [self._insert, self._update, self._insert_or_update,
self._replace, self._delete] if x is not None]) != 1:
raise ValueError(
"No or more than one write mutation operation "
"provided: <%s: %s>" % (self.__class__.__name__, str(self.__dict__)))
def __call__(self, *args, **kwargs):
if self._insert is not None:
return WriteMutation.insert(
table=self._insert, columns=self._columns, values=self._values)
elif self._update is not None:
return WriteMutation.update(
table=self._update, columns=self._columns, values=self._values)
elif self._insert_or_update is not None:
return WriteMutation.insert_or_update(
table=self._insert_or_update,
columns=self._columns,
values=self._values)
elif self._replace is not None:
return WriteMutation.replace(
table=self._replace, columns=self._columns, values=self._values)View on GitHub (pinned to 12126d8942)