apache/beam · error · ValueError
Tag '%s' is neither the main tag '%s' nor any of the tags %s
Error message
Tag '%s' is neither the main tag '%s' nor any of the tags %s
What it means
ValueError raised by DoOutputsTuple.__getitem__ when indexing a multi-output PCollection tuple with a tag that is neither the main tag nor one of the declared side-output tags, and unknown tags are not allowed. It protects against typos in side-output tag access.
Source
Thrown at sdks/python/apache_beam/pvalue.py:293
def __getattr__(self, tag: str) -> PCollection:
# Special methods which may be accessed before the object is
# fully constructed (e.g. in unpickling).
if tag[:2] == tag[-2:] == '__':
return object.__getattr__(self, tag) # type: ignore
return self[tag]
def __getitem__(self, tag: Union[int, str, None]) -> PCollection:
# Accept int tags so that we can look at Partition tags with the
# same ints that we used in the partition function.
# TODO(gildea): Consider requiring string-based tags everywhere.
# This will require a partition function that does not return ints.
if isinstance(tag, int):
tag = str(tag)
if tag == self._main_tag:
tag = None
elif self._tags and tag not in self._tags and not self._allow_unknown_tags:
raise ValueError(
"Tag '%s' is neither the main tag '%s' "
"nor any of the tags %s" % (tag, self._main_tag, self._tags))
# Check if we accessed this tag before.
if tag in self._pcolls:
return self._pcolls[tag]
assert self.producer is not None
if tag is not None:
self._transform.output_tags.add(tag)
is_bounded = all(i.is_bounded for i in self.producer.main_inputs.values())
pcoll = PCollection(
self._pipeline,
tag=tag,
element_type=self._tagged_output_types.get(tag, typehints.Any),
is_bounded=is_bounded)
# Transfer the producer from the DoOutputsTuple to the resulting
# PCollection.
pcoll.producer = self.producer.parts[0]View on GitHub (pinned to 12126d8942)
Solutions
- Use one of the exact tags declared in DoFn.with_outputs(...) / emitted with beam.tag_output
- Check available tags by inspecting the DoFn's output tags before indexing
- Declare with_outputs('*', *extra_tags) or allow_unknown_tags=True if dynamic tags are intended
Example fix
// before main, bad = results['main'], results['badd'] // after main, bad = results[None], results['bad']
Defensive patterns
Strategy: validation
Validate before calling
declared = set(dofn.with_outputs_tags) | {None}
assert tag in declared, f'{tag} not in {declared}' Try / catch
try:
bad = results['bad']
except ValueError as e:
logging.error('Bad side-output tag: %s', e)
bad = results[None] Prevention
- Define side-output tags as module-level string constants shared by DoFn and consumers
- List declared tags before indexing when tags may have changed
- Use results.main (or results[None]) for the primary output instead of guessing tags
When it happens
Trigger: Accessing results['typo_tag'] on the output of a DoFn using beam.tag_output(...) with tags like 'errors'; using an int not emitted via with_outputs declared tags; indexing a tag removed after refactoring.
Common situations: Renaming side-output tags in a DoFn without updating downstream accesses; confusing main output (tag None/'') with declared tags.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- label
- k_val
- Attempting to create a TaggedOutput with non-string tag %s
- Could not find coder for URN " + urn
- Unknown type of encoding context
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/3553b60ee0fcd468.
Report an issue: GitHub.