{"record":{"id":"50d383cbfb064c47","repo":"apache/beam","slug":"in-s-tag-s-is-not-a-string","errorCode":null,"errorMessage":"In %s, tag %s is not a string","messagePattern":"In (.+?), tag (.+?) is not a string","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/common.py","lineNumber":1823,"sourceCode":"        windowed_value.windows *= len(windowed_input_element.windows)\n      return windowed_value\n\n    elif isinstance(result, TimestampedValue):\n      assign_context = WindowFn.AssignContext(result.timestamp, result.value)\n      windowed_value = WindowedValue(\n          result.value, result.timestamp, self.window_fn.assign(assign_context))\n      if len(windowed_input_element.windows) != 1:\n        windowed_value.windows *= len(windowed_input_element.windows)\n      return windowed_value\n\n    else:\n      return windowed_input_element.with_value(result)\n\n  def _handle_tagged_output(self, result):\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      return tag, result.value\n    return None, result\n\n  def _write_value_to_tag(self, tag, windowed_value, watermark_estimator):\n    if watermark_estimator is not None:\n      watermark_estimator.observe_timestamp(windowed_value.timestamp)\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  def _write_batch_to_tag(self, tag, windowed_batch, watermark_estimator):\n    if watermark_estimator is not None:\n      for timestamp in windowed_batch.timestamps:\n        watermark_estimator.observe_timestamp(timestamp)\n\n    if tag is None:","sourceCodeStart":1805,"sourceCodeEnd":1841,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/common.py#L1805-L1841","documentation":"When a DoFn emits a TaggedOutput (for multi-output ParDo via with_outputs), Beam's _handle_tagged_output unwraps it and validates the tag. The tag must be a str because it indexes the tagged_receivers dict for the declared output PCollection. A non-string tag means Beam cannot route the element to the correct output and raises TypeError.","triggerScenarios":"Yielding `TaggedOutput(1, value)` or `TaggedOutput(('a','b'), value)` from a DoFn decorated to produce tagged outputs, where the tag passed to TaggedOutput is not a str.","commonSituations":"Passing an integer enum or tuple as a tag; forgetting that with_outputs() tags declared as strings must match exactly; dynamic tag construction using non-string values.","solutions":["Convert the tag to a string: `TaggedOutput(str(tag), value)`.","Ensure the tag matches one of the outputs declared in `beam.DoFn(...).with_outputs('main', 'other')`.","Add a validation/assertion in the DoFn before constructing the TaggedOutput."],"exampleFix":"// before\nyield TaggedOutput(error_code, element)  # error_code is an int\n// after\nyield TaggedOutput(str(error_code), element)","handlingStrategy":"validation","validationCode":"assert isinstance(tag, str), f'TaggedOutput tag must be str, got {type(tag).__name__}'","typeGuard":"def is_str_tag(tag):\n    return isinstance(tag, str)","tryCatchPattern":"try:\n    out = pipeline_result.wait_until_finish()\nexcept TypeError as e:\n    if 'tag' in str(e) and 'not a string' in str(e):\n        log.error('TaggedOutput tag must be a string matching with_outputs(): %s', e)\n    raise","preventionTips":["Define output tags as module-level string constants and reuse them in both TaggedOutput and with_outputs().","Never construct tags from raw data (ints, enums) without str() conversion.","Test multi-output DoFns with DirectRunner before submitting to a distributed runner."],"tags":["python","apache-beam","tagged-output","type-error"],"backgroundTag":"type-mismatch","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"}