{"record":{"id":"647e6bbe6c3ddd2e","repo":"pandas-dev/pandas","slug":"is-not-a-valid-function-for-type-obj-nam","errorCode":null,"errorMessage":"'{}' is not a valid function for '{type(obj).__name__}' object","messagePattern":"'(.+?)' is not a valid function for '(.+?)' object","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"pandas/core/apply.py","lineNumber":846,"sourceCode":"        assert isinstance(func, str)\n\n        if hasattr(obj, func):\n            f = getattr(obj, func)\n            if callable(f):\n                return f(*args, **kwargs)\n\n            # people may aggregate on a non-callable attribute\n            # but don't let them think they can pass args to it\n            assert len(args) == 0\n            assert not any(kwarg == \"axis\" for kwarg in kwargs)\n            return f\n        elif hasattr(np, func) and hasattr(obj, \"__array__\"):\n            # in particular exclude Window\n            f = getattr(np, func)\n            return f(obj, *args, **kwargs)\n        else:\n            msg = f\"'{func}' is not a valid function for '{type(obj).__name__}' object\"\n            raise AttributeError(msg)\n\n\nclass NDFrameApply(Apply):\n    \"\"\"\n    Methods shared by FrameApply and SeriesApply but\n    not GroupByApply or ResamplerWindowApply\n    \"\"\"\n\n    obj: DataFrame | Series\n\n    @property\n    def index(self) -> Index:\n        return self.obj.index\n\n    @property\n    def agg_axis(self) -> Index:\n        return self.obj._get_agg_axis(self.axis)\n","sourceCodeStart":828,"sourceCodeEnd":864,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/apply.py#L828-L864","documentation":"Raised in `_apply_str` when the string `func` is neither an attribute of the target object nor a numpy function available on its `__array__`. pandas tries `getattr(obj, func)` first, then `getattr(np, func)`; if both fail, it raises AttributeError indicating the name is invalid for this object type.","triggerScenarios":"`df.apply('nonexistent_method')`, `series.apply('mean_x')` (typo), or `df.apply('sqrt')` when 'sqrt' is not a DataFrame method (it is a numpy/Series ufunc but not a DataFrame method). Different object types expose different method sets.","commonSituations":"Typo in a method name; assuming a method exists on DataFrame when it only exists on Series (or vice versa); version upgrades that renamed/removed a method; passing a numpy function name that the object type does not expose.","solutions":["Check that the method exists on the object: `hasattr(df, func)` or `hasattr(np, func)`.","Pass the callable directly instead of a string: `df.apply(np.sqrt)` rather than `df.apply('sqrt')`.","For element-wise numpy functions, use `df.applymap(np.sqrt)` (or `df.map` on newer versions)."],"exampleFix":"# before\ndf.apply('sqrt')\n# after\ndf.apply(np.sqrt)\n# or for element-wise\ndf.map(np.sqrt)","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef resolve_func_name(obj, name):\n    if hasattr(obj, name) and callable(getattr(obj, name)):\n        return name\n    if hasattr(np, name) and hasattr(obj, '__array__'):\n        return name\n    raise AttributeError(f'{name!r} not valid for {type(obj).__name__}')\n\n# usagedf.apply(resolve_func_name(df, candidate))","typeGuard":"def is_valid_func_name(obj, name) -> bool:\n    import numpy as np\n    return (hasattr(obj, name) and callable(getattr(obj, name))) or (hasattr(np, name) and hasattr(obj, '__array__'))","tryCatchPattern":"try:\n    df.apply(name)\nexcept AttributeError as e:\n    if 'is not a valid function' in str(e):\n        df.apply(getattr(np, name))  # fall back to numpy callable\n    else:\n        raise","preventionTips":["Prefer passing callables directly over string method names where possible.","Check `hasattr(df, name)` before dispatching dynamically."],"tags":["pandas","apply","attributeerror","string-dispatch","method-name"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}