{"id":"37192122b7632643","repo":"aio-libs/aiohttp","slug":"session-is-closed","errorCode":null,"errorMessage":"Session is closed","messagePattern":"Session is closed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":503,"sourceCode":"        proxy: StrOrURL | None = None,\n        timeout: ClientTimeout | _SENTINEL | None = sentinel,\n        ssl: SSLContext | bool | Fingerprint | _SENTINEL = sentinel,\n        server_hostname: str | None = None,\n        proxy_headers: LooseHeaders | None = None,\n        trace_request_ctx: object = None,\n        read_bufsize: int | None = None,\n        auto_decompress: bool | None = None,\n        max_line_size: int | None = None,\n        max_field_size: int | None = None,\n        max_headers: int | None = None,\n        middlewares: Sequence[ClientMiddlewareType] | None = None,\n    ) -> ClientResponse:\n        # NOTE: timeout clamps existing connect and read timeouts.  We cannot\n        # set the default to None because we need to detect if the user wants\n        # to use the existing timeouts by setting timeout to None.\n\n        if self.closed:\n            raise RuntimeError(\"Session is closed\")\n\n        method = method.upper()\n\n        if ssl is sentinel:\n            ssl = self._default_ssl\n        if not isinstance(ssl, SSL_ALLOWED_TYPES):\n            raise TypeError(\n                \"ssl should be SSLContext, Fingerprint, or bool, \"\n                f\"got {ssl!r} instead.\"\n            )\n\n        if data is not None and json is not None:\n            raise ValueError(\n                \"data and json parameters can not be used at the same time\"\n            )\n        elif json is not None:\n            if self._json_serialize_bytes is not None:\n                data = payload.JsonBytesPayload(json, dumps=self._json_serialize_bytes)","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/client.py#L485-L521","documentation":"Raised at the top of `ClientSession._request` (client.py:502-503) when `self.closed` is True. A session becomes closed after `.close()` completes or after exiting its `async with` block. Any subsequent call into `request/get/post/ws_connect/...` routes through `_request` and hits this guard before doing any work.","triggerScenarios":"Using the session after `await session.close()`, after the `async with aiohttp.ClientSession() as s:` block exits, or after the connector was closed separately. Also from a `__del__`-triggered path or a fire-and-forget task that outlives the session scope.","commonSituations":"Returning a ClientResponse from an `async with` block and awaiting it later; background tasks holding a session reference after the app shutdown closed it; test fixtures closing the session in teardown while a coroutine is still pending.","solutions":["Ensure all requests finish before the session's `async with` block exits or before `await session.close()`.","Restructure so the session owns the lifetime of the response (read/consume the body inside the context).","Guard call sites: `if not session.closed: await session.get(...)`."],"exampleFix":"// before\nasync with aiohttp.ClientSession() as s:\n    resp = await s.get(url)\nreturn await resp.read()  # block already exited -> Session is closed on next use\n// after\nasync with aiohttp.ClientSession() as s:\n    resp = await s.get(url)\n    return await resp.read()  # consume inside the context","handlingStrategy":"try-catch","validationCode":"def ensure_open(session):\n    if session.closed:\n        raise RuntimeError('ClientSession is closed; create a new one')\n    return session","typeGuard":"def is_session_usable(session) -> bool:\n    return not session.closed","tryCatchPattern":"try:\n    resp = await session.get(url)\nexcept RuntimeError as e:\n    if str(e) == 'Session is closed':\n        session = await new_session()  # rebuild\n        resp = await session.get(url)\n    else:\n        raise","preventionTips":["Scope response reading inside the session's `async with` block.","Check `session.closed` before reusing a cached session.","In background tasks, hold a strong reference to the session for the task's lifetime.","Use `async with` consistently rather than manual close()."],"tags":["client","lifecycle","resource-management","use-after-close"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}