encode/httpx · error · RuntimeError
Cannot send a request, as the client has been closed.
Error message
Cannot send a request, as the client has been closed.
What it means
Raised as RuntimeError by the sync Client.send() path when self._state == ClientState.CLOSED. Once close()/__exit__ has run the client refuses any further requests.
Source
Thrown at httpx/_client.py:901
stream: bool = False,
auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
) -> Response:
"""
Send a request.
The request is sent as-is, unmodified.
Typically you'll want to build one with `Client.build_request()`
so that any client-level configuration is merged into the request,
but passing an explicit `httpx.Request()` is supported as well.
See also: [Request instances][0]
[0]: /advanced/clients/#request-instances
"""
if self._state == ClientState.CLOSED:
raise RuntimeError("Cannot send a request, as the client has been closed.")
self._state = ClientState.OPENED
follow_redirects = (
self.follow_redirects
if isinstance(follow_redirects, UseClientDefault)
else follow_redirects
)
self._set_timeout(request)
auth = self._build_request_auth(request, auth)
response = self._send_handling_auth(
request,
auth=auth,
follow_redirects=follow_redirects,
history=[],
)View on GitHub (pinned to b5addb64f0)
Solutions
- Perform all requests inside a single 'with httpx.Client() as client:' block.
- If the client was closed, construct a fresh httpx.Client instead of reusing it.
- Avoid calling client.close() (or exiting its context) before outstanding requests finish.
Example fix
// before
with httpx.Client() as c:
pass
c.get(url) # RuntimeError: closed
// after
with httpx.Client() as c:
c.get(url) Defensive patterns
Strategy: validation
Validate before calling
import httpx
def ensure_open(client: httpx.Client) -> None:
if client.is_closed:
raise RuntimeError("client is closed; create a new httpx.Client")
ensure_open(client)
client.get(url) Type guard
import httpx
def is_usable(client: httpx.Client) -> bool:
return not client.is_closed Try / catch
try:
client.get(url)
except RuntimeError as exc:
if "has been closed" in str(exc):
client = httpx.Client(...) # recreate
client.get(url)
else:
raise Prevention
- Keep all requests inside the client's 'with' block.
- Check client.is_closed before reusing a stored client.
- Never share a client with code that may close it concurrently.
When it happens
Trigger: Calling client.get/send/client.stream after client.close(), or after the 'with client:' block has exited (which sets state to CLOSED).
Common situations: Reusing a client stored globally after it was closed; issuing requests outside the with-block; a shared client closed by one consumer while another still uses it.
Related errors
- Cannot open a client instance more than once.
- Cannot reopen a client instance, once it has been closed.
- Exceeded maximum allowed redirects.
- Attempted to send an async request with a sync Client instan
- Multiple cookies exist with name={name}
AI-assisted analysis of encode/httpx@b5addb64f0 (2026-08-04).
Data as JSON: /data/errors/e0c6993e2caabbcc.json.
Report an issue: GitHub.