encode/httpx · error · RuntimeError

Cannot open a client instance more than once.

Error message

Cannot open a client instance more than once.

What it means

Raised as RuntimeError by sync Client.__enter__ when self._state is already OPENED. A client may be used as a context manager only once; entering it a second time while still open is rejected.

Source

Thrown at httpx/_client.py:1283

        Close transport and proxies.
        """
        if self._state != ClientState.CLOSED:
            self._state = ClientState.CLOSED

            self._transport.close()
            for transport in self._mounts.values():
                if transport is not None:
                    transport.close()

    def __enter__(self: T) -> T:
        if self._state != ClientState.UNOPENED:
            msg = {
                ClientState.OPENED: "Cannot open a client instance more than once.",
                ClientState.CLOSED: (
                    "Cannot reopen a client instance, once it has been closed."
                ),
            }[self._state]
            raise RuntimeError(msg)

        self._state = ClientState.OPENED

        self._transport.__enter__()
        for transport in self._mounts.values():
            if transport is not None:
                transport.__enter__()
        return self

    def __exit__(
        self,
        exc_type: type[BaseException] | None = None,
        exc_value: BaseException | None = None,
        traceback: TracebackType | None = None,
    ) -> None:
        self._state = ClientState.CLOSED

        self._transport.__exit__(exc_type, exc_value, traceback)

View on GitHub (pinned to b5addb64f0)

Solutions

  1. Use the client inside a single 'with' block; do not nest with-statements on the same instance.
  2. Create a separate httpx.Client for the nested scope.
  3. Drop the context manager and just use the client directly (it lazily opens on first request).

Example fix

// before
with client:
    with client:  # RuntimeError: more than once
        client.get(url)
// after
with client:
    client.get(url)
Defensive patterns

Strategy: validation

Validate before calling

import httpx
# never enter the same client twice; track entry yourself
assert not getattr(client, "_entered", False), "client already entered"
client._entered = True
with client:
    client.get(url)

Type guard

import httpx
from httpx._client import ClientState

def can_enter(client: httpx.Client) -> bool:
    return client._state == ClientState.UNOPENED

Try / catch

try:
    with client:
        client.get(url)
except RuntimeError as exc:
    if "more than once" in str(exc):
        client2 = httpx.Client(...)
        with client2:
            client2.get(url)
    else:
        raise

Prevention

When it happens

Trigger: Calling client.__enter__() twice, or nesting two 'with client:' blocks on the same instance (the inner __enter__ sees state OPENED).

Common situations: Sharing one client across nested with-blocks; a helper function that opens the same client already opened by its caller.

Related errors


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