{"record":{"id":"b020983d861bf145","repo":"apache/beam","slug":"unknown-operation-action-s","errorCode":null,"errorMessage":"Unknown operation action: %s","messagePattern":"Unknown operation action: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/gcp/experimental/spannerio.py","lineNumber":1261,"sourceCode":"    self.batches.inc()\n    try:\n      with self._db_instance.batch() as b:\n        for m in element:\n          table_id = m.kwargs['table']\n          self._register_table_metric(table_id)\n\n          if m.operation == WriteMutation._OPERATION_DELETE:\n            batch_func = b.delete\n          elif m.operation == WriteMutation._OPERATION_REPLACE:\n            batch_func = b.replace\n          elif m.operation == WriteMutation._OPERATION_INSERT_OR_UPDATE:\n            batch_func = b.insert_or_update\n          elif m.operation == WriteMutation._OPERATION_INSERT:\n            batch_func = b.insert\n          elif m.operation == WriteMutation._OPERATION_UPDATE:\n            batch_func = b.update\n          else:\n            raise ValueError(\"Unknown operation action: %s\" % m.operation)\n          batch_func(**m.kwargs)\n    except (ClientError, GoogleAPICallError) as e:\n      for service_metric in self.service_metrics.values():\n        service_metric.call(str(e.code.value))\n      raise\n    else:\n      for service_metric in self.service_metrics.values():\n        service_metric.call('ok')\n\n\n@with_input_types(typing.Union[MutationGroup, _Mutator])\n@with_output_types(MutationGroup)\nclass _MakeMutationGroupsFn(DoFn):\n  \"\"\"\n  Make Mutation group object if the element is the instance of _Mutator.\n  \"\"\"\n  def process(self, element):\n    if isinstance(element, MutationGroup):","sourceCodeStart":1243,"sourceCodeEnd":1279,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/gcp/experimental/spannerio.py#L1243-L1279","documentation":"In the Spanner write batch processing DoFn, each WriteMutation's operation kind is dispatched to the corresponding batch method (insert/update/insert_or_update/replace/delete). If a mutation carries an unrecognized operation value, the library raises this ValueError because no batch method exists for it.","triggerScenarios":"A WriteMutation object with a corrupted or hand-crafted _operation value (e.g. constructed by bypassing the class factory methods and setting operation directly), or a custom subclass introducing a new operation string not handled in process().","commonSituations":"Deserializing WriteMutation objects across Beam worker versions where operation constants differ; monkey-patching or pickling mutations between SDK versions.","solutions":["Create mutations only via WriteMutation.insert/update/insert_or_update/replace/delete factory methods.","Do not mutate the _operation attribute directly.","Ensure the Beam SDK version used to serialize mutations matches the worker's SDK version (check beam_version in pipeline options)."],"exampleFix":"# before\nm = WriteMutation.__new__(WriteMutation); m._operation = 'upsert'\n# after\nm = WriteMutation.insert_or_update(table, rows)","handlingStrategy":"try-catch","validationCode":"def valid_mutation(m):\n    return getattr(m, 'operation', None) in {\n        WriteMutation._OPERATION_INSERT, WriteMutation._OPERATION_UPDATE,\n        WriteMutation._OPERATION_INSERT_OR_UPDATE, WriteMutation._OPERATION_REPLACE,\n        WriteMutation._OPERATION_DELETE}","typeGuard":null,"tryCatchPattern":"try:\n    output = pcoll | spannerwrite\nexcept ValueError as e:\n    if 'Unknown operation action' in str(e):\n        logging.error('Corrupt WriteMutation operation in stream: %s', e)\n    raise","preventionTips":["Only create mutations via WriteMutation factory methods","Keep SDK versions consistent between job submission and runners (pickling of constants)","Never set _operation manually"],"tags":["apache-beam","google-cloud-spanner","dispatch","valueerror"],"backgroundTag":"invalid-enum-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}