{"record":{"id":"1eefcdc395ae802b","repo":"apache/beam","slug":"merging-requested-for-non-mergeable-state-tag-r","errorCode":null,"errorMessage":"Merging requested for non-mergeable state tag: %r.","messagePattern":"Merging requested for non-mergeable state tag: %r\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/trigger.py","lineNumber":1138,"sourceCode":"    self.counter = None\n\n  def set_timer(\n      self, window, name, time_domain, timestamp, dynamic_timer_tag=''):\n    self.raw_state.set_timer(\n        self._get_id(window),\n        name,\n        time_domain,\n        timestamp,\n        dynamic_timer_tag=dynamic_timer_tag)\n\n  def clear_timer(self, window, name, time_domain, dynamic_timer_tag=''):\n    for window_id in self._get_ids(window):\n      self.raw_state.clear_timer(\n          window_id, name, time_domain, dynamic_timer_tag=dynamic_timer_tag)\n\n  def add_state(self, window, tag, value):\n    if isinstance(tag, _ReadModifyWriteStateTag):\n      raise ValueError(\n          'Merging requested for non-mergeable state tag: %r.' % tag)\n    elif isinstance(tag, _CombiningValueStateTag):\n      tag = tag.without_extraction()\n    self.raw_state.add_state(self._get_id(window), tag, value)\n\n  def get_state(self, window, tag):\n    if isinstance(tag, _CombiningValueStateTag):\n      original_tag, tag = tag, tag.without_extraction()\n    values = [\n        self.raw_state.get_state(window_id, tag)\n        for window_id in self._get_ids(window)\n    ]\n    if isinstance(tag, _ReadModifyWriteStateTag):\n      raise ValueError(\n          'Merging requested for non-mergeable state tag: %r.' % tag)\n    elif isinstance(tag, _CombiningValueStateTag):\n      return original_tag.combine_fn.extract_output(\n          original_tag.combine_fn.merge_accumulators(values))","sourceCodeStart":1120,"sourceCodeEnd":1156,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/trigger.py#L1120-L1156","documentation":"MergingTriggerState.add_state refuses to add a value under a _ReadModifyWriteStateTag, because RMW state cannot be merged across windows - only combining, list, set, and watermark-hold state tags support merging. The library raises ValueError to prevent silently corrupting state during window merge.","triggerScenarios":"Calling merging-state add_state(window, tag, value) with a _ReadModifyWriteStateTag (the tag type used by simple bag/RMW state) while the trigger driver is merging window state.","commonSituations":"Custom trigger or state code that mixes ReadModifyWriteStateTag with a merging trigger driver; code written against the non-merging TriggerDriver then reused in grouped/merging pipelines.","solutions":["Use a _CombiningValueStateTag (with a CombineFn) instead of a _ReadModifyWriteStateTag when state must merge across windows.","Restructure so the RMW value is per-window and never participates in merging.","If the tag is a combining tag, ensure merging code goes through the _CombiningValueStateTag branch (without_extraction) as the driver expects."],"exampleFix":"// before\ntag = _ReadModifyWriteStateTag('count')\nstate.add_state(window, tag, 1)  # merging state -> ValueError\n// after\ntag = _CombiningValueStateTag('count', combiners.CountCombineFn())\nstate.add_state(window, tag, 1)","handlingStrategy":"type-guard","validationCode":"from apache_beam.transforms.trigger import _ReadModifyWriteStateTag\nif isinstance(tag, _ReadModifyWriteStateTag):\n    raise TypeError('Use a mergeable (combining/list/set/watermark-hold) tag in merging state')","typeGuard":"def is_mergeable_tag(tag):\n    from apache_beam.transforms import trigger as t\n    return isinstance(tag, (t._CombiningValueStateTag, t._ListStateTag, t._SetStateTag, t._WatermarkHoldStateTag))","tryCatchPattern":"try:\n    state.add_state(window, tag, value)\nexcept ValueError as e:\n    logger.error('Non-mergeable tag in merging state: %s', e)\n    raise","preventionTips":["In merging trigger drivers, only use combining/list/set/watermark-hold tags.","Model counters as _CombiningValueStateTag with CountCombineFn, not RMW tags.","Review custom triggers for tag-class choices when switching to streaming/merging execution."],"tags":["python","apache-beam","trigger","state","merging"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}