{"record":{"id":"75947b94ea58417c","repo":"apache/beam","slug":"number-of-components-does-not-match-number-of-coders","errorCode":null,"errorMessage":"Number of components does not match number of coders.","messagePattern":"Number of components does not match number of coders\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/coders/coder_impl.py","lineNumber":1161,"sourceCode":"  \"\"\"For internal use only; no backwards-compatibility guarantees.\n\n  CoderImpl for coders that are comprised of several component coders.\"\"\"\n  def __init__(self, coder_impls):\n    for c in coder_impls:\n      assert isinstance(c, CoderImpl), c\n    self._coder_impls = tuple(coder_impls)\n\n  def _extract_components(self, value):\n    raise NotImplementedError\n\n  def _construct_from_components(self, components):\n    raise NotImplementedError\n\n  def encode_to_stream(self, value, out, nested):\n    # type: (Any, create_OutputStream, bool) -> None\n    values = self._extract_components(value)\n    if len(self._coder_impls) != len(values):\n      raise ValueError('Number of components does not match number of coders.')\n    for i in range(0, len(self._coder_impls)):\n      c = self._coder_impls[i]  # type cast\n      c.encode_to_stream(\n          values[i], out, nested or i + 1 < len(self._coder_impls))\n\n  def decode_from_stream(self, in_stream, nested):\n    # type: (create_InputStream, bool) -> Any\n    return self._construct_from_components([\n        c.decode_from_stream(\n            in_stream, nested or i + 1 < len(self._coder_impls))\n        for i, c in enumerate(self._coder_impls)\n    ])\n\n  def estimate_size(self, value, nested=False):\n    # type: (Any, bool) -> int\n\n    \"\"\"Estimates the encoded size of the given value, in bytes.\"\"\"\n    # TODO(ccy): This ignores sizes of observable components.","sourceCodeStart":1143,"sourceCodeEnd":1179,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/coders/coder_impl.py#L1143-L1179","documentation":"TupleCoderImpl.encode_to_stream extracts the components of a tuple-like value and requires exactly one component coder per component. If the value's component count differs from the number of coders the TupleCoder was constructed with, Beam raises ValueError because there is no defined way to encode the mismatched shape.","triggerScenarios":"Encoding a value whose _extract_components() yields a different number of items than the coder list given to TupleCoderImpl._construct_from / TupleCoder — e.g., encoding a 3-tuple with a coder built for 2 fields, or a typed row whose fields changed since the coder was created.","commonSituations":"Schema/PCollection type changed (field added/removed) between writer and reader; reusing a cached or deserialized coder against new data shapes; passing plain tuples of varying length into a DoFn output coded by a fixed TupleCoder.","solutions":["Ensure the values emitted match the arity the TupleCoder was built for (same number of components)","Recreate the TupleCoder from the current value type/schema so coder count matches components","If the schema changed, re-generate coders (let Beam infer from the new type hint) instead of reusing stale ones","For variable-length data use a sequence/list coder rather than a fixed-arity TupleCoder"],"exampleFix":"// before\nencoder = TupleCoder((VarIntCoder(), StrUtf8Coder()))  # 2 coders\nencoder.encode((1, 'a', True))  # 3 components -> ValueError\n// after\nencoder = TupleCoder((VarIntCoder(), StrUtf8Coder(), BooleanCoder()))\nencoder.encode((1, 'a', True))","handlingStrategy":"validation","validationCode":"components = value if isinstance(value, tuple) else tuple(extract_components(value))\nassert len(components) == len(coder_impls), \\\n    f'expected {len(coder_impls)} components, got {len(components)}'","typeGuard":"def matches_arity(value, coder) -> bool:\n    return len(tuple(value)) == len(coder._coder_impls)","tryCatchPattern":"try:\n    coder.encode(value)\nexcept ValueError as e:\n    if 'components' in str(e):\n        raise TypeError(f'{value!r} does not match coder arity: {e}') from e\n    raise","preventionTips":["Derive the TupleCoder from the same type/schema as the values being emitted","Re-create coders whenever the record shape changes instead of caching stale ones","Use DoFn type hints so Beam infers matching coders automatically"],"tags":["python","apache-beam","coding","tuple","arity-mismatch"],"backgroundTag":"shape-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-15T13:17:12.816Z"}