{"id":"8a2da99571e96c3d","repo":"encode/httpx","slug":"cannot-open-a-client-instance-more-than-once","errorCode":null,"errorMessage":"Cannot open a client instance more than once.","messagePattern":"Cannot open a client instance more than once\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"httpx/_client.py","lineNumber":1283,"sourceCode":"        Close transport and proxies.\n        \"\"\"\n        if self._state != ClientState.CLOSED:\n            self._state = ClientState.CLOSED\n\n            self._transport.close()\n            for transport in self._mounts.values():\n                if transport is not None:\n                    transport.close()\n\n    def __enter__(self: T) -> T:\n        if self._state != ClientState.UNOPENED:\n            msg = {\n                ClientState.OPENED: \"Cannot open a client instance more than once.\",\n                ClientState.CLOSED: (\n                    \"Cannot reopen a client instance, once it has been closed.\"\n                ),\n            }[self._state]\n            raise RuntimeError(msg)\n\n        self._state = ClientState.OPENED\n\n        self._transport.__enter__()\n        for transport in self._mounts.values():\n            if transport is not None:\n                transport.__enter__()\n        return self\n\n    def __exit__(\n        self,\n        exc_type: type[BaseException] | None = None,\n        exc_value: BaseException | None = None,\n        traceback: TracebackType | None = None,\n    ) -> None:\n        self._state = ClientState.CLOSED\n\n        self._transport.__exit__(exc_type, exc_value, traceback)","sourceCodeStart":1265,"sourceCodeEnd":1301,"githubUrl":"https://github.com/encode/httpx/blob/b5addb64f0161ff6bfe94c124ef76f6a1fba5254/httpx/_client.py#L1265-L1301","documentation":"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.","triggerScenarios":"Calling client.__enter__() twice, or nesting two 'with client:' blocks on the same instance (the inner __enter__ sees state OPENED).","commonSituations":"Sharing one client across nested with-blocks; a helper function that opens the same client already opened by its caller.","solutions":["Use the client inside a single 'with' block; do not nest with-statements on the same instance.","Create a separate httpx.Client for the nested scope.","Drop the context manager and just use the client directly (it lazily opens on first request)."],"exampleFix":"// before\nwith client:\n    with client:  # RuntimeError: more than once\n        client.get(url)\n// after\nwith client:\n    client.get(url)","handlingStrategy":"validation","validationCode":"import httpx\n# never enter the same client twice; track entry yourself\nassert not getattr(client, \"_entered\", False), \"client already entered\"\nclient._entered = True\nwith client:\n    client.get(url)","typeGuard":"import httpx\nfrom httpx._client import ClientState\n\ndef can_enter(client: httpx.Client) -> bool:\n    return client._state == ClientState.UNOPENED","tryCatchPattern":"try:\n    with client:\n        client.get(url)\nexcept RuntimeError as exc:\n    if \"more than once\" in str(exc):\n        client2 = httpx.Client(...)\n        with client2:\n            client2.get(url)\n    else:\n        raise","preventionTips":["Enter each client exactly once; do not nest with-blocks on one instance.","Prefer a single long-lived with-block over repeated entries.","Avoid context-managing a client you don't own."],"tags":["lifecycle","context-manager","sync"],"analyzedSha":"b5addb64f0161ff6bfe94c124ef76f6a1fba5254","analyzedAt":"2026-08-04T19:32:56.768Z","schemaVersion":2}