{"record":{"id":"c8995c0e710b8e71","repo":"pytest-dev/pytest","slug":"target-r-has-no-attribute-name-r","errorCode":null,"errorMessage":"{target!r} has no attribute {name!r}","messagePattern":"(.+?) has no attribute (.+?)","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/monkeypatch.py","lineNumber":242,"sourceCode":"            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,\n        name: str | NotSetType = NOTSET,\n        raising: bool = True,\n    ) -> None:\n        \"\"\"Delete attribute ``name`` from ``target``.\n\n        If no ``name`` is specified and ``target`` is a string\n        it will be interpreted as a dotted import path with the\n        last part being the attribute name.","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/monkeypatch.py#L224-L260","documentation":"An AttributeError raised by MonkeyPatch.setattr when raising=True (the default) and the target does not already have the named attribute. pytest refuses to create brand-new attributes by default to catch typos and patches against the wrong object; oldval is NOTSET when getattr returns the sentinel. The message shows the target repr and the attribute name.","triggerScenarios":"Calling `monkeypatch.setattr(obj, 'nonexistent', value)` with the default raising=True on an object that lacks the attribute; or `monkeypatch.setattr('mymod.X.typo', value)` where the attribute name is misspelled.","commonSituations":"Typos in the attribute name, patching the wrong class/module (e.g. a copy vs the original), version skew where the attribute was removed, or genuinely intending to add a new attribute without opting in.","solutions":["Verify the attribute exists on the exact object you are patching (use hasattr).","Pass `raising=False` if you intentionally want to create a new attribute.","Correct the dotted path to point at the object that actually owns the attribute (beware re-exports)."],"exampleFix":"# before\nmonkeypatch.setattr(obj, 'attr_name', value)\n# AttributeError: <Obj> has no attribute 'attr_name'\n# after\nmonkeypatch.setattr(obj, 'real_attr', value)\n# or, to create a new attribute:\nmonkeypatch.setattr(obj, 'attr_name', value, raising=False)","handlingStrategy":"validation","validationCode":"def can_patch(obj, name) -> bool:\n    return hasattr(obj, name)","typeGuard":null,"tryCatchPattern":"try:\n    monkeypatch.setattr(obj, 'attr', value)\nexcept AttributeError:\n    monkeypatch.setattr(obj, 'attr', value, raising=False)","preventionTips":["Use hasattr to confirm the attribute before patching.","Pass raising=False only when intentionally creating a new attribute.","Patch the object that truly owns the attribute."],"tags":["pytest","monkeypatch","attribute-error","setattr","raising"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}