{"record":{"id":"5fa13589e59a19ea","repo":"apache/beam","slug":"tuplecoder-does-not-have-exactly-2-components","errorCode":null,"errorMessage":"TupleCoder does not have exactly 2 components.","messagePattern":"TupleCoder does not have exactly 2 components\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/coders/coders.py","lineNumber":1338,"sourceCode":"    # type: (typehints.TupleConstraint, CoderRegistry) -> TupleCoder\n    return cls([registry.get_coder(t) for t in typehint.tuple_types])\n\n  def _get_component_coders(self):\n    # type: () -> Tuple[Coder, ...]\n    return self.coders()\n\n  def coders(self):\n    # type: () -> Tuple[Coder, ...]\n    return self._coders\n\n  def is_kv_coder(self):\n    # type: () -> bool\n    return len(self._coders) == 2\n\n  def key_coder(self):\n    # type: () -> Coder\n    if len(self._coders) != 2:\n      raise ValueError('TupleCoder does not have exactly 2 components.')\n    return self._coders[0]\n\n  def value_coder(self):\n    # type: () -> Coder\n    if len(self._coders) != 2:\n      raise ValueError('TupleCoder does not have exactly 2 components.')\n    return self._coders[1]\n\n  def __repr__(self):\n    return 'TupleCoder[%s]' % ', '.join(str(c) for c in self._coders)\n\n  def __eq__(self, other):\n    return type(self) == type(other) and self._coders == other.coders()\n\n  def __hash__(self):\n    return hash(self._coders)\n\n  def to_runner_api_parameter(self, context):","sourceCodeStart":1320,"sourceCodeEnd":1356,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/coders/coders.py#L1320-L1356","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nTupleCoder([coder_a, coder_b, coder_c]).key_coder()\n// after\nTupleCoder([coder_ab, coder_c]).key_coder()  # or TupleCoder([coder_a, coder_b])","handlingStrategy":"validation","validationCode":"if len(coder._coders) != 2:\n    raise ValueError(f'expected KV coder, got {len(coder._coders)} components')\nkc = coder.key_coder()","typeGuard":"def is_pair_coder(coder) -> bool:\n    from apache_beam.coders import TupleCoder\n    return isinstance(coder, TupleCoder) and len(coder._coders) == 2","tryCatchPattern":"try:\n    kc = coder.key_coder()\nexcept ValueError as e:\n    log.error('coder is not a KV pair coder: %s', coder)\n    raise","preventionTips":["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"],"tags":["python","coders","apache-beam"],"backgroundTag":"invalid-argument-value","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"}