encode/httpx · error · ResponseNotRead
Attempted to access streaming response content, without havi
Error message
Attempted to access streaming response content, without having called `read()`.
What it means
Raised as `ResponseNotRead` (a `StreamError` subclass) by the `Response.content` property when no `_content` attribute exists yet. For a streaming response (one whose body has not been buffered), httpx will not implicitly read the network; you must call `.read()` (sync) or `.aread()` (async) first. Accessing `.content`, `.text`, or `.json()` before that triggers this error.
Source
Thrown at httpx/_models.py:638
def reason_phrase(self) -> str:
try:
reason_phrase: bytes = self.extensions["reason_phrase"]
except KeyError:
return codes.get_reason_phrase(self.status_code)
else:
return reason_phrase.decode("ascii", errors="ignore")
@property
def url(self) -> URL:
"""
Returns the URL for which the request was made.
"""
return self.request.url
@property
def content(self) -> bytes:
if not hasattr(self, "_content"):
raise ResponseNotRead()
return self._content
@property
def text(self) -> str:
if not hasattr(self, "_text"):
content = self.content
if not content:
self._text = ""
else:
decoder = TextDecoder(encoding=self.encoding or "utf-8")
self._text = "".join([decoder.decode(self.content), decoder.flush()])
return self._text
@property
def encoding(self) -> str | None:
"""
Return an encoding to use for decoding the byte content into text.
The priority for determining this is given by...View on GitHub (pinned to b5addb64f0)
Solutions
- Inside a streaming context, call `response.read()` (sync) or `await response.aread()` (async) before accessing `.content`/`.text`/`.json()`.
- If you always want the full body, drop `stream=True` / `client.stream(...)` and use plain `client.get(...)` which reads automatically.
- For an already-closed stream, re-issue the request rather than retrying `.read()`.
- Use `iter_raw`/`iter_bytes`/`aiter_bytes` if you want to consume the body incrementally instead of buffering.
Example fix
// before
with client.stream('GET', url) as r:
pass
print(r.text) # ResponseNotRead
// after
with client.stream('GET', url) as r:
r.read()
print(r.text) Defensive patterns
Strategy: validation
Validate before calling
def is_read(resp: httpx.Response) -> bool:
return hasattr(resp, '_content') Type guard
import httpx
def response_is_buffered(resp: httpx.Response) -> bool:
return hasattr(resp, '_content') Try / catch
try:
body = response.content
except httpx.ResponseNotRead:
await response.aread() # or response.read() for sync
body = response.content Prevention
- Call read()/aread() inside every streaming context before touching the body.
- Use non-streaming client.get() when you always want the full body.
- Centralize body access in one helper so the read step is never skipped.
When it happens
Trigger: Calling `client.stream('GET', url)` (or `client.send(req, stream=True)`), then inside or after the context reading `response.text`/`response.content`/`response.json()` without first awaiting/calling `response.aread()`/`response.read()`. Also reproducible by manually building `httpx.Response(200, stream=...)` and touching `.content`.
Common situations: Migrating from `requests` where `r.text` lazily read the body; forgetting that `with client.stream(...)` does NOT auto-read the body; mixing sync `.read()` with an async client.
Related errors
- Attempted to read or stream some content, but the content ha
- Attempted to read or stream content, but the stream has been
- The request instance has not been set on this response.
- Cannot call `raise_for_status` as the request instance has n
- Attempted to call a sync iterator on an async stream.
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/18ce8ab2b718d4b1.json.
Report an issue: GitHub.