{"record":{"id":"9eb1ff78c175b787","repo":"apache/beam","slug":"combiner-input-type-must-be-specified-positionally","errorCode":null,"errorMessage":"Combiner input type must be specified positionally.","messagePattern":"Combiner input type must be specified positionally\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/core.py","lineNumber":1344,"sourceCode":"    else:\n      return [self._fn(accumulator, *args, **kwargs)]\n\n  def extract_output(self, accumulator, *args, **kwargs):\n    return self._fn(accumulator, *args, **kwargs)\n\n  def default_type_hints(self):\n    fn_type_hints = typehints.decorators.IOTypeHints.from_callable(self._fn)\n    type_hints = get_type_hints(self._fn).with_defaults(fn_type_hints)\n    if type_hints.input_types is None:\n      return type_hints\n    else:\n      # fn(Iterable[V]) -> V becomes CombineFn(V) -> V\n      input_args, input_kwargs = type_hints.input_types\n      if not input_args:\n        if len(input_kwargs) == 1:\n          input_args, input_kwargs = tuple(input_kwargs.values()), {}\n        else:\n          raise TypeError('Combiner input type must be specified positionally.')\n      if not is_consistent_with(input_args[0],\n                                typehints.Iterable[typehints.Any]):\n        raise TypeCheckError(\n            'All functions for a Combine PTransform must accept a '\n            'single argument compatible with: Iterable[Any]. '\n            'Instead a function with input type: %s was received.' %\n            input_args[0])\n      input_args = (element_type(input_args[0]), ) + input_args[1:]\n      # TODO(robertwb): Assert output type is consistent with input type?\n      return type_hints.with_input_types(*input_args, **input_kwargs)\n\n  def infer_output_type(self, input_type):\n    return _strip_output_annotations(\n        trivial_inference.infer_return_type(self._fn, [input_type]))\n\n  def for_input_type(self, input_type):\n    # Avoid circular imports.\n    from apache_beam.transforms import cy_combiners","sourceCodeStart":1326,"sourceCodeEnd":1362,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/core.py#L1326-L1362","documentation":" When wrapping a type-hinted callable as a CombineFn, Beam derives the input type from the function's type hints. If no positional input argument hint exists (only keyword-arg hints, and not exactly one of them), it cannot determine the combiner input type, so it raises this TypeError.","triggerScenarios":"Passing a function annotated only with keyword arguments (e.g. def f(*, data: List[int]) -> int) or with no input annotation at all plus multiple/zero kwarg hints, to CallableWrapperCombineFn / CombineFn.from_callable / beam.Combine.","commonSituations":"Adding type hints to an existing combine function using keyword-only parameters; using functools.wraps or wrappers that strip positional annotations; libraries that emit functions with kwonly args.","solutions":["Annotate the single input parameter positionally: def f(xs: Iterable[int]) -> int.","If using kwonly args, collapse to exactly one positional parameter.","Explicitly set input/output type hints via with_input_types/with_output_types on the PTransform instead of relying on inference.","Remove conflicting extra keyword hints or provide exactly one keyword hint.","Example fix: `def f(data: List[int]) -> int` (positional) instead of `def f(*, data: List[int]) -> int`."],"exampleFix":"// before\ndef combiner(*, data: List[int]) -> int: ...\npcoll | beam.Combine(combiner)\n// after\ndef combiner(data: Iterable[int]) -> int: ...\npcoll | beam.Combine(combiner)","handlingStrategy":"validation","validationCode":"hints = typing.get_type_hints(fn)\npositional = [k for k in hints if k != 'return']\nif not positional:\n    raise TypeError('combiner fn needs a positional input annotation')","typeGuard":"def has_positional_input_hint(fn) -> bool:\n    params = inspect.signature(fn).parameters\n    return any(p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD)\n               for p in params.values())","tryCatchPattern":null,"preventionTips":["Annotate the combine fn's single input positionally (e.g. Iterable[int]).","Avoid keyword-only parameters in combine functions.","Keep __annotations__ intact; avoid decorators that strip type hints."],"tags":["python","apache-beam","type-hints","combine"],"backgroundTag":"type-mismatch","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"}