psf/requests · error · AttributeError
'{type(self).__name__}' object has no attribute '{key}'
Error message
'{type(self).__name__}' object has no attribute '{key}' What it means
requests.structures.LookupDict (used for requests.codes, the status-code lookup) overrides __getattr__ to serve attribute access from the instance __dict__ and raise a standard-style AttributeError for anything not present. So requests.codes.ok works, but a misspelled or nonexistent code name raises this error. Note __getitem__ deliberately falls through to None instead, so bracket access never raises — an intentional asymmetry.
Source
Thrown at src/requests/structures.py:114
class LookupDict(dict[str, _VT]):
"""Dictionary lookup object."""
name: Any
def __init__(self, name: Any = None) -> None:
self.name = name
super().__init__()
def __repr__(self) -> str:
return f"<lookup '{self.name}'>"
def __getattr__(self, key: str) -> _VT | None:
# We need this for type checkers to infer typing
# on attribute access with status_codes.py
if key in self.__dict__:
return self.__dict__[key]
else:
raise AttributeError(
f"'{type(self).__name__}' object has no attribute '{key}'"
)
def __getitem__(self, key: str) -> _VT | None: # type: ignore[override]
# We allow fall-through here, so values default to None
return self.__dict__.get(key, None)
@overload
def get(self, key: str, default: None = None) -> _VT | None: ...
@overload
def get(self, key: str, default: _D | _VT) -> _D | _VT: ...
def get(self, key: str, default: _D | None = None) -> _VT | _D | None:
return self.__dict__.get(key, default)
View on GitHub ↗ (pinned to 414f0513c3)
Solutions
- Fix the attribute name — check valid aliases in requests.status_codes (e.g. requests.codes.ok, requests.codes.not_found, requests.codes.teapot)
- Compare against integer literals or http.HTTPStatus instead: response.status_code == 404
- If a soft lookup is intended, use bracket access (requests.codes['maybe_missing'] returns None) or getattr with a default
Example fix
# before
if r.status_code == requests.codes.no_found: # AttributeError
...
# after
if r.status_code == requests.codes.not_found:
... Defensive patterns
Strategy: try-catch
Validate before calling
key = "Content-Type" value = headers.get(key) # returns None instead of raising
Type guard
def has_header(mapping, key):
return key in mapping # CaseInsensitiveDict membership is case-insensitive Try / catch
try:
value = obj.some_attr
except AttributeError:
value = None # attribute-style access on requests structures raises AttributeError for unknown keys Prevention
- Access headers via dict-style headers.get('Name') rather than attribute-style access
- Rely on 'key in response.headers' membership tests before indexing
- Remember header lookups are case-insensitive, but attribute access on these objects is not a supported API
When it happens
Trigger: Accessing an attribute that isn't a registered status-code name on requests.codes (e.g. requests.codes.okay, requests.codes.not_found_ with a typo), or attribute access on any other LookupDict instance for a key never inserted. Raised at src/requests/structures.py:110-116.
Common situations: Typos in status-code names (requests.codes.no_found); guessing names that aren't in the alias table; code written against dict-style access assuming attribute access has the same return-None behavior as lookup['missing']; static-analysis-invisible dynamic attributes making these errors appear only at runtime.
Related errors
- Unsupported event specified, with event name "{event}"
- Invalid timeout {timeout}. Pass a (connect, read) timeout tu
- cannot encode objects that are not 2-tuples
- Files must be provided.
- Data must not be a string.
AI-assisted analysis of psf/requests@414f0513c3 (2026-07-31).
Data as JSON: /data/errors/671f252897e54f03.json.
Report an issue: GitHub ↗.