encode/httpx · error · RuntimeError

The request instance has not been set on this response.

Error message

The request instance has not been set on this response.

What it means

Raised by the `Response.request` property when `_request` is None. httpx links a Response to the Request that produced it at send time; if that link was never established, accessing `.request`, `.url`, or `.next_request` is undefined, so the property refuses to return a stale/empty value. This almost always means the Response was constructed by hand (tests, mocks, fixtures, or a custom transport) rather than returned by `client.request`/`client.get`.

Source

Thrown at httpx/_models.py:601

        """
        if not hasattr(self, "_elapsed"):
            raise RuntimeError(
                "'.elapsed' may only be accessed after the response "
                "has been read or closed."
            )
        return self._elapsed

    @elapsed.setter
    def elapsed(self, elapsed: datetime.timedelta) -> None:
        self._elapsed = elapsed

    @property
    def request(self) -> Request:
        """
        Returns the request instance associated to the current response.
        """
        if self._request is None:
            raise RuntimeError(
                "The request instance has not been set on this response."
            )
        return self._request

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

    @property
    def http_version(self) -> str:
        try:
            http_version: bytes = self.extensions["http_version"]
        except KeyError:
            return "HTTP/1.1"
        else:
            return http_version.decode("ascii", errors="ignore")

    @property

View on GitHub (pinned to b5addb64f0)

Solutions

  1. Pass a real request when constructing: `httpx.Response(200, request=httpx.Request('GET', url))`.
  2. In tests, use `httpx.MockTransport` or `respx` so httpx itself wires the request onto the Response.
  3. Guard before access: `if response._request is not None:` (private but stable) or restructure so you never need `.request` on synthetic responses.
  4. If you only need the URL, store it separately instead of relying on `response.url`, which delegates to `response.request.url`.

Example fix

// before
resp = httpx.Response(200, content=b'ok')
print(resp.url)  # RuntimeError

// after
req = httpx.Request('GET', 'https://example.com/')
resp = httpx.Response(200, content=b'ok', request=req)
print(resp.url)
Defensive patterns

Strategy: validation

Validate before calling

def safe_request(resp: httpx.Response) -> httpx.Request | None:
    return getattr(resp, '_request', None)

Type guard

import httpx

def has_request(resp: httpx.Response) -> bool:
    return getattr(resp, '_request', None) is not None

Try / catch

try:
    req = response.request
except RuntimeError:
    # synthetic response - synthesize a request or skip
    req = None

Prevention

When it happens

Trigger: Calling `httpx.Response(200, content=b'...').request`, `response.url`, or any code path that reads `self.request` on a Response built via the `httpx.Response(...)` constructor without a `request=` argument. Also triggered by `raise_for_status()` on such a Response (see error 43) and by `extract_cookies` flows that dereference `response.request`.

Common situations: Unit tests that build a fake `httpx.Response` for a mock transport but forget to pass `request=httpx.Request('GET', 'https://example.com')`; custom `httpx.BaseTransport`/`AsyncBaseTransport` implementations that return a hand-built Response; upgrading from `requests` where manually building Response-like objects was common.

Related errors


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