encode/httpx · warning · RuntimeError

The .request property has not been set.

Error message

The .request property has not been set.

What it means

RuntimeError('The .request property has not been set.') raised by the HTTPError.request getter. Every HTTPError stores an optional _request; the getter raises if it is None. This happens when you catch an exception (typically constructed outside a request_context) and access .request before httpx has had a chance to attach one — e.g. an exception raised during client construction, an event hook, or an exception you constructed/raised manually.

Source

Thrown at httpx/_exceptions.py:99

    For example:

    ```
    try:
        response = httpx.get("https://www.example.com")
        response.raise_for_status()
    except httpx.HTTPError as exc:
        print(f"HTTP Exception for {exc.request.url} - {exc}")
    ```
    """

    def __init__(self, message: str) -> None:
        super().__init__(message)
        self._request: Request | None = None

    @property
    def request(self) -> Request:
        if self._request is None:
            raise RuntimeError("The .request property has not been set.")
        return self._request

    @request.setter
    def request(self, request: Request) -> None:
        self._request = request


class RequestError(HTTPError):
    """
    Base class for all exceptions that may occur when issuing a `.request()`.
    """

    def __init__(self, message: str, *, request: Request | None = None) -> None:
        super().__init__(message)
        # At the point an exception is raised we won't typically have a request
        # instance to associate it with.
        #
        # The 'request_context' context manager is used within the Client and

View on GitHub (pinned to b5addb64f0)

Solutions

  1. Guard with `if exc._request is not None:` or use getattr(exc, '_request', None) before accessing.
  2. Prefer catching the specific exception types and only accessing .request when you know a request is in flight.
  3. When raising httpx exceptions yourself, pass request=<the request> so the property is set.
  4. Wrap the access in try/except RuntimeError and degrade gracefully.

Example fix

// before
try:
    resp = client.get(url)
except httpx.HTTPError as exc:
    print(exc.request.url)  # RuntimeError if request not set
// after
try:
    resp = client.get(url)
except httpx.HTTPError as exc:
    req = getattr(exc, '_request', None)
    print(req.url if req else '<no request>')
Defensive patterns

Strategy: type-guard

Validate before calling

# Use the private _request attribute defensively
req = getattr(exc, '_request', None)
url = req.url if req is not None else '<no request>'

Type guard

def exception_has_request(exc: 'httpx.HTTPError') -> bool:
    return getattr(exc, '_request', None) is not None

Try / catch

try:
    resp = client.get(url)
except httpx.HTTPError as exc:
    req = getattr(exc, '_request', None)
    if req is not None:
        log.warning('request to %s failed: %s', req.url, exc)
    else:
        log.warning('httpx error (no request attached): %s', exc)

Prevention

When it happens

Trigger: Accessing exc.request on a TimeoutException/NetworkError raised before the request was dispatched; accessing .request inside an exception handler that caught an HTTPError raised by user code (not httpx); event hooks that raise; manually raising httpx.ConnectError('msg') without passing request= and then reading .request.

Common situations: Logging middleware that does `print(exc.request.url)` for any caught HTTPError; retry decorators accessing exc.request; manually raising httpx exceptions in tests; transport-level errors fired before a Request object existed.

Related errors


AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04). Data as JSON: /data/errors/7149be99b640ed17.json. Report an issue: GitHub.