apache/beam · error · ValueError

Main output tag %r must be different from side output tags…

Error message

Main output tag %r must be different from side output tags %r.

What it means

When a ParDo declares multiple outputs, each output is identified by a tag. The main output tag and side output tags must be distinct namespaces; Beam raises this ValueError at transform validation time if the requested main tag collides with one of the side output tags.

Solutions

  1. Rename the colliding side output tag so it differs from the main tag.
  2. Explicitly choose a distinct main tag, e.g. with_outputs('side1', main='primary').
  3. Deduplicate/validate the tag list programmatically before calling with_outputs (set difference between tags and main).

Example fix

// before
pardo.with_outputs('main', 'main', 'other')
// after
pardo.with_outputs('main', 'side_main', 'other')
Defensive patterns

Strategy: validation

Validate before calling

tags = ['side1', 'side2']
main = 'main'
assert main not in tags, f'main tag {main!r} collides with side tags {tags}'

Type guard

def tags_are_disjoint(main, tags):
    return main not in tags

Try / catch

try:
    pardo = pardo.with_outputs(*tags, main=main)
except ValueError as e:
    logger.error('Output tag collision: %s', e)
    raise

Prevention

When it happens

Trigger: Calling pardo.with_outputs('main', *side_tags) or with_outputs(tag, main='tag') where the main tag string is also present in the side output tags tuple.

Common situations: Copy-paste of tag strings; defaulting main='main' while also passing 'main' as a side tag; dynamically built tag lists that accidentally include the main tag.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/9c6eccaa81b3f4f6. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/transforms/core.py:1837

        be used for the main output (which will not have a tag associated with
        it).

    Returns:
      ~apache_beam.pvalue.DoOutputsTuple: An object of type
      :class:`~apache_beam.pvalue.DoOutputsTuple` that bundles together all
      the outputs of a :class:`ParDo` transform and allows accessing the
      individual :class:`~apache_beam.pvalue.PCollection` s for each output
      using an ``object.tag`` syntax.

    Raises:
      TypeError: if the **self** object is not a
        :class:`~apache_beam.pvalue.PCollection` that is the result of a
        :class:`ParDo` transform.
      ValueError: if **main_kw** contains any key other than
        ``'main'``.
    """
    if main in tags:
      raise ValueError(
          'Main output tag %r must be different from side output tags %r.' %
          (main, tags))
    type_hints = self.get_type_hints()
    declared_tags = set(type_hints.tagged_output_types().keys())
    requested_tags = set(tags)

    unknown = requested_tags - declared_tags
    if unknown and declared_tags:  # Only warn if type hints exist
      logging.warning(
          "Tags %s requested in with_outputs() but not declared "
          "in type hints. Declared tags: %s",
          unknown,
          declared_tags)
    return _MultiParDo(self, tags, main, allow_unknown_tags)

  def _do_fn_info(self):
    return DoFnInfo.create(self.fn, self.args, self.kwargs)

View on GitHub (pinned to 12126d8942)