{"record":{"id":"0171f74a4bb544a0","repo":"apache/beam","slug":"finish-bundle-should-only-output-windowedvalue-type-but-got","errorCode":null,"errorMessage":"Finish Bundle should only output WindowedValue type but got %s","messagePattern":"Finish Bundle should only output WindowedValue type but got (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/common.py","lineNumber":1879,"sourceCode":"\n    A value wrapped in a TaggedOutput object will be unwrapped and\n    then dispatched to the appropriate indexed output.\n    \"\"\"\n    if results is None:\n      return\n\n    for result in results:\n      tag = None\n      if isinstance(result, TaggedOutput):\n        tag = result.tag\n        if not isinstance(tag, str):\n          raise TypeError('In %s, tag %s is not a string' % (self, tag))\n        result = result.value\n\n      if isinstance(result, WindowedValue):\n        windowed_value = result\n      else:\n        raise RuntimeError('Finish Bundle should only output WindowedValue ' +\\\n                           'type but got %s' % type(result))\n\n      if tag is None:\n        self.main_receivers.receive(windowed_value)\n      else:\n        self.tagged_receivers[tag].receive(windowed_value)\n\n\nclass _NoContext(WindowFn.AssignContext):\n  \"\"\"An uninspectable WindowFn.AssignContext.\"\"\"\n  NO_VALUE = object()\n\n  def __init__(self, value, timestamp=NO_VALUE):\n    self.value = value\n    self._timestamp = timestamp\n\n  @property\n  def timestamp(self):","sourceCodeStart":1861,"sourceCodeEnd":1897,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/common.py#L1861-L1897","documentation":"finish_bundle must emit only WindowedValue objects because bundle-finish outputs carry window/timestamp metadata needed downstream. _any_ other result type (including a raw TimestampedValue, str, dict, etc.) triggers this RuntimeError in finish_bundle_outputs.","triggerScenarios":"finish_bundle yields plain values like `yield ('key', count)` or `yield TimestampedValue(v, ts)` instead of `yield WindowedValue(v, ts, window)`.","commonSituations":"Writing aggregation/summary logic in finish_bundle and forgetting to wrap results with beam.window.TimestampedValue(...).in_window(...) / WindowedValue; assuming Beam auto-wraps finish_bundle outputs like it does for process().","solutions":["Wrap each finish_bundle result: `yield WindowedValue(value, timestamp, [window])`, commonly via `beam.window.TimestampedValue(value, ts)` only in process — in finish_bundle construct WindowedValue directly.","Ensure timestamps are within allowed lateness/allowed timestamp bounds (windowing strategy).","Check the existing_windows of inputs (via DoFn.process context) and reuse them for outputs."],"exampleFix":"// before\ndef finish_bundle(self):\n    yield ('total', self.total)\n// after\ndef finish_bundle(self):\n    yield WindowedValue(('total', self.total), self.last_ts, self.window)","handlingStrategy":"validation","validationCode":"assert all(isinstance(r, (WindowedValue, TaggedOutput)) for r in finish_bundle_results), 'finish_bundle must yield WindowedValue'","typeGuard":"def is_windowed_output(r):\n    v = r.value if isinstance(r, TaggedOutput) else r\n    return isinstance(v, WindowedValue)","tryCatchPattern":"try:\n    invoker.invoke_finish_bundle()\nexcept RuntimeError as e:\n    if 'Finish Bundle should only output WindowedValue' in str(e):\n        raise ValueError('Wrap finish_bundle outputs in WindowedValue') from e\n    raise","preventionTips":["Always construct WindowedValue(value, timestamp, [window]) in finish_bundle.","Capture the window/timestamp from the last processed element to reuse in finish_bundle outputs.","Test finish_bundle paths with the DirectRunner where output validation runs."],"tags":["python","apache-beam","finish-bundle","windowed-value","runtime-error"],"backgroundTag":"incompatible-return-type","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"}