{"record":{"id":"8ac87c87cf61b631","repo":"apache/beam","slug":"func-must-be-specified-and-it-must-be-callable","errorCode":null,"errorMessage":"func must be specified and it must be callable","messagePattern":"func must be specified and it must be callable","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/dataframe/frames.py","lineNumber":4457,"sourceCode":"              **kwargs).droplevel(self._grouping_columns),\n            [self._ungrouped_with_index],\n            proxy=proxy,\n            requires_partition_by=partitionings.Index(levels),\n            preserves_partition_by=partitionings.Index(self._grouping_indexes)))\n\n  @frame_base.with_docs_from(DataFrameGroupBy)\n  def pipe(self, func, *args, **kwargs):\n    if isinstance(func, tuple):\n      func, data = func\n      kwargs[data] = self\n      return func(*args, **kwargs)\n\n    return func(self, *args, **kwargs)\n\n  @frame_base.with_docs_from(DataFrameGroupBy)\n  def filter(self, func=None, dropna=True):\n    if func is None or not callable(func):\n      raise TypeError(\"func must be specified and it must be callable\")\n\n    def apply_fn(df):\n      if func(df):\n        return df\n      elif not dropna:\n        result = df.copy()\n        result.iloc[:, :] = np.nan\n        return result\n      else:\n        return df.iloc[:0]\n\n    return self.apply(apply_fn).droplevel(self._grouping_columns)\n\n  @property  # type: ignore\n  @frame_base.with_docs_from(DataFrameGroupBy)\n  def dtypes(self):\n    return frame_base.DeferredFrame.wrap(\n        expressions.ComputedExpression(","sourceCodeStart":4439,"sourceCodeEnd":4475,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/dataframe/frames.py#L4439-L4475","documentation":"DeferredGroupBy.filter() raises TypeError when `func` is None or not callable. Beam requires an explicit callable predicate deciding which groups to keep; there is no default behavior and string shortcuts are not accepted.","triggerScenarios":"Calling df.groupby('k').filter() with no argument, or filter('name')/filter(non_callable) on a Beam deferred DataFrame.","commonSituations":"Omitting the predicate accidentally after refactoring; copying pandas code that passed a string; assuming filter() with no args is a no-op like dropna-only filtering.","solutions":["Pass a callable predicate: df.groupby('k').filter(lambda df: df['v'].sum() > 0).","If you intended to aggregate, use .agg(...) or .apply(...) instead of .filter(...).","Guard the call site with `if callable(f): gb.filter(f)`."],"exampleFix":"# before\ndf.groupby('k').filter('sum')\n# after\ndf.groupby('k').filter(lambda df: df['v'].sum() > 0)","handlingStrategy":"type-guard","validationCode":"if func is None or not callable(func):\n    raise TypeError('filter requires a callable predicate')","typeGuard":"def is_valid_filter_fn(func) -> bool:\n    return func is not None and callable(func)","tryCatchPattern":"try:\n    out = beam_df.groupby('k').filter(func)\nexcept TypeError as e:\n    if 'func must be specified' in str(e):\n        raise ValueError('Provide a callable predicate to groupby.filter') from e","preventionTips":["Never call groupby.filter without an argument.","Keep filter predicates as explicit lambdas/functions.","Lint for groupby(...).filter() calls with empty argument lists."],"tags":["apache-beam","dataframe","type-error","callable-required"],"backgroundTag":"missing-required-argument","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"}