apache/beam · error · ValueError
Invalid object type: . Object must be an instance of…
Error message
Invalid object type: %s. Object must be an instance of MutationGroup or WriteMutations
What it means
SpannerIO's Write DoFn (process) accepts only MutationGroup instances or _Mutator (WriteMutation) objects to write to Spanner. Any other element type on the PCollection entering SpannerWrite triggers this ValueError.
Solutions
- Wrap each element: beam.Map(lambda row: WriteMutation.insert(table, [row])) before SpannerWrite.
- Group several mutations per element with MutationGroup([...]).
- If piping a PCollection of MutationGroup already, verify upstream transforms do not unpack them back to raw rows.
Example fix
# before
rows | 'write' >> spannerio.SpannerWrite(project, instance, database)
# after
rows | 'to_mut' >> beam.Map(lambda r: WriteMutation.insert('tbl', [r])) | 'write' >> spannerio.SpannerWrite(project, instance, database) Defensive patterns
Strategy: type-guard
Validate before calling
def validate_mutation_elements(pcoll):
from apache_beam.io.gcp.experimental.spannerio import MutationGroup
def check(el):
if not isinstance(el, (MutationGroup,)) and not hasattr(el, 'operation'):
raise TypeError('Element %r must be MutationGroup or WriteMutation' % el)
return el
return pcoll | beam.Map(check) Type guard
def is_spanner_writable(el):
from apache_beam.io.gcp.experimental.spannerio import MutationGroup
from apache_beam.io.gcp.experimental.spannerio import _Mutator
return isinstance(el, (MutationGroup, _Mutator)) Prevention
- Map records to WriteMutation before SpannerWrite
- Use MutationGroup for multi-row elements
- Check upstream transforms don't unwrap mutation wrappers
When it happens
Trigger: Piping a PCollection of dicts, rows, or tuples directly into spannerio.SpannerWrite / WriteToSpanner without wrapping each element in WriteMutation or MutationGroup.
Common situations: Coming from other Beam sinks where you pipe plain records directly (e.g. like WriteToBigQuery with dicts) and expecting SpannerWrite to accept raw rows; missing the WriteMutation() wrapping step.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- No or more than one write mutation operation provided: <
- Read operation in the constructor only works with the root…
- Spanner required read operation, sql or table with columns.
- Unknown operation action
- A sink must inherit iobase.Sink, iobase.NativeSink, or be a…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/8dceda54aa718074.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/io/gcp/experimental/spannerio.py:1284
raise
else:
for service_metric in self.service_metrics.values():
service_metric.call('ok')
@with_input_types(typing.Union[MutationGroup, _Mutator])
@with_output_types(MutationGroup)
class _MakeMutationGroupsFn(DoFn):
"""
Make Mutation group object if the element is the instance of _Mutator.
"""
def process(self, element):
if isinstance(element, MutationGroup):
yield element
elif isinstance(element, _Mutator):
yield MutationGroup([element])
else:
raise ValueError(
"Invalid object type: %s. Object must be an instance of "
"MutationGroup or WriteMutations" % str(element))
class _WriteGroup(PTransform):
def __init__(self, max_batch_size_bytes, max_number_rows, max_number_cells):
self._max_batch_size_bytes = max_batch_size_bytes
self._max_number_rows = max_number_rows
self._max_number_cells = max_number_cells
def expand(self, pcoll):
filter_batchable_mutations = (
pcoll
| 'Making mutation groups' >> ParDo(_MakeMutationGroupsFn())
| 'Filtering Batchable Mutations' >> ParDo(
_BatchableFilterFn(
max_batch_size_bytes=self._max_batch_size_bytes,
max_number_rows=self._max_number_rows,View on GitHub (pinned to 12126d8942)