{"record":{"id":"f599fc6dd3fc243f","repo":"pytest-dev/pytest","slug":"use-setattr-target-name-value-with-name-being-a","errorCode":null,"errorMessage":"use setattr(target, name, value) with name being a string or setattr(target, value) with target being a dotted import string","messagePattern":"use setattr\\(target, name, value\\) with name being a string or setattr\\(target, value\\) with target being a dotted import string","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/monkeypatch.py","lineNumber":234,"sourceCode":"        See the section :ref:`Where to patch <python:where-to-patch>` in the :mod:`unittest.mock`\n        docs for a complete explanation, which is meant for :func:`unittest.mock.patch` but\n        applies to ``monkeypatch.setattr`` as well.\n        \"\"\"\n        __tracebackhide__ = True\n        import inspect\n\n        if value is NOTSET:\n            if not isinstance(target, str):\n                raise TypeError(\n                    \"use setattr(target, name, value) or \"\n                    \"setattr(target, value) with target being a dotted \"\n                    \"import string\"\n                )\n            value = name\n            name, target = derive_importpath(target, raising)\n        else:\n            if not isinstance(name, str):\n                raise TypeError(\n                    \"use setattr(target, name, value) with name being a string or \"\n                    \"setattr(target, value) with target being a dotted \"\n                    \"import string\"\n                )\n\n        oldval = getattr(target, name, NOTSET)\n        if raising and oldval is NOTSET:\n            raise AttributeError(f\"{target!r} has no attribute {name!r}\")\n\n        # avoid class descriptors like staticmethod/classmethod\n        if inspect.isclass(target):\n            oldval = target.__dict__.get(name, NOTSET)\n        setattr(target, name, value)\n        self._setattr.append((target, name, oldval))\n\n    def delattr(\n        self,\n        target: object | str,","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/monkeypatch.py#L216-L252","documentation":"A TypeError raised by MonkeyPatch.setattr when the three-argument form is used (value is provided) but the `name` argument is not a string. pytest requires the attribute name to be a string when patching a concrete target object. Passing an int, None, or any non-string as the name triggers this guard.","triggerScenarios":"Calling `monkeypatch.setattr(obj, 123, value)`, `monkeypatch.setattr(obj, None, value)`, or `monkeypatch.setattr(obj, ['attr'], value)`. The branch `value is not NOTSET and not isinstance(name, str)` fires.","commonSituations":"Passing a computed attribute name that is None; mixing positional arguments; confusing the order of (target, name, value).","solutions":["Ensure the second positional argument (name) is a string naming the attribute.","If the name is dynamic, coerce to str or validate before calling.","Double-check argument order: (target, name, value)."],"exampleFix":"# before\nmonkeypatch.setattr(obj, attr_name if cond else None, value)\n# after\nmonkeypatch.setattr(obj, str(attr_name), value)","handlingStrategy":"type-guard","validationCode":"def is_setattr_name(name) -> bool:\n    return isinstance(name, str)","typeGuard":"def is_valid_attribute_name(name) -> bool:\n    return isinstance(name, str) and len(name) > 0","tryCatchPattern":null,"preventionTips":["Always pass a string attribute name in the three-arg form.","Coerce dynamic names with str() after a None-check.","Keep argument order: (target, name, value)."],"tags":["pytest","monkeypatch","type-error","setattr","argument-validation"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}