apache/beam · error · ValueError
TupleCoder does not have exactly 2 components.
Error message
TupleCoder does not have exactly 2 components.
What it means
TupleCoder represents a key-value pair and key_coder() only makes sense when it has exactly two component coders. If the coder was constructed with any other number of components, accessing key_coder() raises ValueError rather than returning an index that would silently be wrong.
Solutions
- Ensure the TupleCoder is constructed from exactly a KV (2-tuple) typehint or two coders
- Inspect coder._coders to confirm the component count before accessing key/value coders
- If more components are needed, nest TupleCoders (TupleCoder[TupleCoder[A,B],C]) instead of a flat 3-coder TupleCoder
Example fix
// before TupleCoder([coder_a, coder_b, coder_c]).key_coder() // after TupleCoder([coder_ab, coder_c]).key_coder() # or TupleCoder([coder_a, coder_b])
Defensive patterns
Strategy: validation
Validate before calling
if len(coder._coders) != 2:
raise ValueError(f'expected KV coder, got {len(coder._coders)} components')
kc = coder.key_coder() Type guard
def is_pair_coder(coder) -> bool:
from apache_beam.coders import TupleCoder
return isinstance(coder, TupleCoder) and len(coder._coders) == 2 Try / catch
try:
kc = coder.key_coder()
except ValueError as e:
log.error('coder is not a KV pair coder: %s', coder)
raise Prevention
- Build TupleCoders from exactly two coders or a KV typehint
- Use coder.is_kv_coder() / is_deterministic checks in custom coder plumbing
- Nest coders rather than widening a flat TupleCoder beyond 2 components
When it happens
Trigger: Calling key_coder() on a TupleCoder whose _coders list length != 2, e.g. a TupleCoder built from a 3-element tuple typehint or via deserialization of a malformed coder payload.
Common situations: Custom coder plumbing/hand-written CoGroupByKey coders; decoding a coder from the runner/harness that was serialized with a different component count; constructing TupleCoder manually with wrong arity.
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
- Bad coder for input of
- Bad coder for output of
- Encountered a type that is not currently supported by…
- Expected a strict subclass of…
- Expected a subclass of proto.Message, but got a
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5fa13589e59a19ea.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/coders/coders.py:1338
# type: (typehints.TupleConstraint, CoderRegistry) -> TupleCoder
return cls([registry.get_coder(t) for t in typehint.tuple_types])
def _get_component_coders(self):
# type: () -> Tuple[Coder, ...]
return self.coders()
def coders(self):
# type: () -> Tuple[Coder, ...]
return self._coders
def is_kv_coder(self):
# type: () -> bool
return len(self._coders) == 2
def key_coder(self):
# type: () -> Coder
if len(self._coders) != 2:
raise ValueError('TupleCoder does not have exactly 2 components.')
return self._coders[0]
def value_coder(self):
# type: () -> Coder
if len(self._coders) != 2:
raise ValueError('TupleCoder does not have exactly 2 components.')
return self._coders[1]
def __repr__(self):
return 'TupleCoder[%s]' % ', '.join(str(c) for c in self._coders)
def __eq__(self, other):
return type(self) == type(other) and self._coders == other.coders()
def __hash__(self):
return hash(self._coders)
def to_runner_api_parameter(self, context):View on GitHub (pinned to 12126d8942)