pytest-dev/pytest · error · AttributeError
object at has no attribute
Error message
{type(obj).__name__!r} object at {ann} has no attribute {name!r} What it means
An AttributeError raised by annotated_getattr when an object along the dotted import path does not have the requested attribute. Unlike a bare getattr, this version annotates the error with the type of the object and the human-readable path segment, making it easier to locate which part of 'a.b.c' was missing the attribute.
Solutions
- Verify the attribute exists: `python -c 'from mymod import MyClass; print(hasattr(MyClass, 'attr'))'`.
- Check the spelling and the class/module you are patching; use the leaf object directly.
- Pass raising=False if you intend to create a new attribute (for setattr).
- Update the path to match the current library version.
Example fix
# before
monkeypatch.setattr('mymod.MyClass.notamethod', new)
# after
monkeypatch.setattr('mymod.MyClass.realmethod', new) Defensive patterns
Strategy: validation
Validate before calling
def attr_exists(dotted: str) -> bool:
parts = dotted.rsplit('.', 1)
if len(parts) != 2:
return False
mod, attr = parts
try:
import importlib
target = importlib.import_module(mod)
except ImportError:
return False
return hasattr(target, attr) Try / catch
try:
monkeypatch.setattr('mymod.X.attr', value)
except AttributeError as e:
# the message names the type and missing attribute
... Prevention
- Use hasattr to confirm the attribute before patching.
- Patch the object that actually owns the attribute, not a re-export.
- Keep attribute names in sync with library upgrades.
When it happens
Trigger: Calling `monkeypatch.setattr('mymod.MyClass.missing_attr', value)` where MyClass exists but `missing_attr` does not; or `monkeypatch.delattr` on a non-existent attribute with raising=True. The annotated path is the module string passed in.
Common situations: Typos in the attribute name, version skew where an attribute was renamed/removed, patching a method that lives on a subclass, or wrong module re-export.
Related errors
- has no attribute
- import error in
- must be absolute import path string, not
- use setattr(target, name, value) or setattr(target, value)…
- use setattr(target, name, value) with name being a string…
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/f58a4dd2d1ed3ba4.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/monkeypatch.py:97
# We use explicit un-nesting of the handling block in order
# to avoid nested exceptions.
try:
importlib.import_module(used)
except ImportError as ex:
expected = str(ex).split()[-1]
if expected == used:
raise
else:
raise ImportError(f"import error in {used}: {ex}") from ex
found = annotated_getattr(found, part, used)
return found
def annotated_getattr(obj: object, name: str, ann: str) -> object:
try:
obj = getattr(obj, name)
except AttributeError as e:
raise AttributeError(
f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}"
) from e
return obj
def derive_importpath(import_path: str, raising: bool) -> tuple[str, object]:
if not isinstance(import_path, str) or "." not in import_path:
raise TypeError(f"must be absolute import path string, not {import_path!r}")
module, attr = import_path.rsplit(".", 1)
target = resolve(module)
if raising:
annotated_getattr(target, attr, ann=module)
return attr, target
@final
class MonkeyPatch:
"""Helper to conveniently monkeypatch attributes/items/environmentView on GitHub (pinned to 0d6fbdeffa)