encode/httpx · warning · RequestNotRead
Attempted to access streaming request content, without havin
Error message
Attempted to access streaming request content, without having called `read()`.
What it means
This is httpx.RequestNotRead raised by the Request.content property when _content has not been materialized yet. Unlike Response.content (which triggers a read), Request.content requires you to have explicitly called request.read() (or aread()) first, because a streaming request body cannot be auto-read without side effects on the underlying generator.
Source
Thrown at httpx/_models.py:465
auto_headers: list[tuple[bytes, bytes]] = []
has_host = "Host" in self.headers
has_content_length = (
"Content-Length" in self.headers or "Transfer-Encoding" in self.headers
)
if not has_host and self.url.host:
auto_headers.append((b"Host", self.url.netloc))
if not has_content_length and self.method in ("POST", "PUT", "PATCH"):
auto_headers.append((b"Content-Length", b"0"))
self.headers = Headers(auto_headers + self.headers.raw)
@property
def content(self) -> bytes:
if not hasattr(self, "_content"):
raise RequestNotRead()
return self._content
def read(self) -> bytes:
"""
Read and return the request content.
"""
if not hasattr(self, "_content"):
assert isinstance(self.stream, typing.Iterable)
self._content = b"".join(self.stream)
if not isinstance(self.stream, ByteStream):
# If a streaming request has been read entirely into memory, then
# we can replace the stream with a raw bytes implementation,
# to ensure that any non-replayable streams can still be used.
self.stream = ByteStream(self._content)
return self._content
async def aread(self) -> bytes:
"""View on GitHub (pinned to b5addb64f0)
Solutions
- Call request.read() (sync) or await request.aread() (async) before accessing .content.
- Build the Request with content=<bytes> instead of a generator so .content is immediately available.
- Use request.stream only when you genuinely want streaming, and read() before inspection.
- In middleware, guard: if not hasattr(request, '_content'): request.read().
Example fix
// before
req = httpx.Request('POST', url, content=gen)
print(req.content) # RequestNotRead
// after
req = httpx.Request('POST', url, content=gen)
req.read()
print(req.content)
# or simpler:
req = httpx.Request('POST', url, content=b'...bytes...')
print(req.content) Defensive patterns
Strategy: validation
Validate before calling
# Ensure the request body is materialized before accessing .content
if not hasattr(request, '_content'):
request.read() # sync; use await request.aread() for async
body = request.content Type guard
def request_content_ready(request: 'httpx.Request') -> bool:
return hasattr(request, '_content') Try / catch
try:
body = request.content
except httpx.RequestNotRead:
request.read()
body = request.content Prevention
- Call request.read()/aread() before inspecting .content.
- Build Requests with content=<bytes> when you need immediate .content access.
- In middleware, guard: if not hasattr(request, '_content'): request.read().
- Avoid passing generators as content for Requests you intend to inspect.
When it happens
Trigger: Calling request.content on a freshly built Request whose body is still a stream/generator and you have not called read(); inspecting a Request that was sent with content=<generator> before reading; mocking a Request without materializing its content.
Common situations: Logging/inspection middleware that reads request.content before the request is sent; test assertions on a constructed-but-unsent Request; building a Request manually with stream=<generator> and accessing .content.
Related errors
- Attempted to send an async request with a sync Client instan
- Attempted to send a sync request with an AsyncClient instanc
- Attempted to read or stream some content, but the content ha
- Attempted to read or stream content, but the stream has been
- The .request property has not been set.
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/9f0a568f8f9273df.json.
Report an issue: GitHub.