{"record":{"id":"d420b46ee13c714c","repo":"apache/beam","slug":"expected-a-combinefn-or-callable-got-r","errorCode":null,"errorMessage":"Expected a CombineFn or callable, got %r","messagePattern":"Expected a CombineFn or callable, got %r","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/core.py","lineNumber":1245,"sourceCode":"      input_type: the type of input elements.\n    \"\"\"\n    return self\n\n  @staticmethod\n  def from_callable(fn):\n    return CallableWrapperCombineFn(fn)\n\n  @staticmethod\n  def maybe_from_callable(fn, has_side_inputs=True):\n    # type: (typing.Union[CombineFn, typing.Callable], bool) -> CombineFn\n    if isinstance(fn, CombineFn):\n      return fn\n    elif callable(fn) and not has_side_inputs:\n      return NoSideInputsCallableWrapperCombineFn(fn)\n    elif callable(fn):\n      return CallableWrapperCombineFn(fn)\n    else:\n      raise TypeError('Expected a CombineFn or callable, got %r' % fn)\n\n  def get_accumulator_coder(self):\n    return coders.registry.get_coder(object)\n\n  urns.RunnerApiFn.register_pickle_urn(python_urns.PICKLED_COMBINE_FN)\n\n\nclass _ReiterableChain(object):\n  \"\"\"Like itertools.chain, but allowing re-iteration.\"\"\"\n  def __init__(self, iterables):\n    self.iterables = iterables\n\n  def __iter__(self):\n    for iterable in self.iterables:\n      for item in iterable:\n        yield item\n\n  def __bool__(self):","sourceCodeStart":1227,"sourceCodeEnd":1263,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/core.py#L1227-L1263","documentation":" apache_beam.transforms.core.CombineFn.maybe_from_callable raises this TypeError when given a value that is neither a CombineFn instance nor a callable. The library requires a combiner with a defined reduce strategy; anything else cannot be turned into a CombineFn.","triggerScenarios":"Calling CombineFn.maybe_from_callable(x) (directly or via CombineGlyph / Combine PTransform wiring) with None, a string, a class (not instance), or another non-callable object.","commonSituations":"Passing the wrong variable (e.g. None from a failed factory function or an unset config) as the combine function; passing a class object like `sum` vs a proper callable; refactoring that renamed a combiner function so the name now binds to something else.","solutions":["Pass a callable (e.g. a function or lambda) or a CombineFn instance to maybe_from_callable / Combine().","Print and inspect the value being passed; if it is None, fix the upstream code that was supposed to produce the function.","If passing a class, instantiate it first (MyCombineFn() not MyCombineFn).","Wrap a simple aggregation in a lambda or def so it is callable, e.g. lambda xs: sum(xs)."],"exampleFix":"// before\nbeam.Combine(maybe_combiner)  # maybe_combiner is None\n// after\nif not (isinstance(maybe_combiner, CombineFn) or callable(maybe_combiner)):\n    raise ValueError(f'bad combiner: {maybe_combiner!r}')\np = pcoll | beam.Combine(maybe_combiner or (lambda xs: sum(xs)))","handlingStrategy":"validation","validationCode":"if not (isinstance(fn, CombineFn) or callable(fn)):\n    raise TypeError(f'combiner must be CombineFn or callable, got {fn!r}')","typeGuard":"def is_combine_fn(x) -> bool:\n    return isinstance(x, CombineFn) or callable(x)","tryCatchPattern":null,"preventionTips":["Always pass named functions/lambdas or CombineFn subclasses to beam.Combine.","Check for None coming from optional imports or config before building the pipeline.","Never pass classes where instances (or plain functions) are expected."],"tags":["python","apache-beam","typecheck","combinfn"],"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-14T16:17:12.679Z"}