aiohttp Unclosed client session (tested)

aiohttp warns Unclosed client session when a ClientSession is garbage-collected without being closed. Use async with aiohttp.ClientSession() or await session.close(), and reuse one session.

1. Reproduce it

import asyncio, gc, aiohttp
async def main():
    s = aiohttp.ClientSession()        # never closed
    print("closed?", s.closed)
asyncio.run(main())
gc.collect()

Output:

closed? False
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7f6be46592b0>

aiohttp prints Unclosed client session when a ClientSession that was never closed is garbage-collected. The session owns a connection pool, so the warning means sockets may have been left open.

2. Fix: async with (or await close())

import asyncio, aiohttp
async def main():
    async with aiohttp.ClientSession() as s:
        pass
    print("closed?", s.closed)
asyncio.run(main())
print("no warning")

Output:

closed? True
no warning

Use async with aiohttp.ClientSession() as s:, or call await s.close() in a finally block. Create one session and reuse it for many requests rather than one per request; a long-lived session belongs to your app's startup/shutdown (e.g. a FastAPI lifespan), closed on shutdown.

3. Creating a session outside the event loop

import aiohttp
s = aiohttp.ClientSession()            # created outside a running loop

Output:

Traceback (most recent call last):
  File "/w/b3.py", line 2, in <module>
    s = aiohttp.ClientSession()            # created outside a running loop
  File "/usr/local/lib/python3.14/site-packages/aiohttp/client.py", line 374, in __init__
    loop = loop or asyncio.get_running_loop()
                   ~~~~~~~~~~~~~~~~~~~~~~~~^^
RuntimeError: no running event loop

aiohttp 3.14 refuses to create a session at import time or module level: it needs a running loop. Create it inside an async function.

Related: asyncio Task exception was never retrieved, asyncio Event loop is closed.

Frequently asked questions

What causes aiohttp Unclosed client session?

A ClientSession was garbage-collected without close(). Use async with or await session.close().

Can I create an aiohttp ClientSession at module level?

Not in aiohttp 3.14.5: it raises RuntimeError: no running event loop. Create it inside an async function.

Written with AI assistance. Measured on 2026-10-23 with aiohttp 3.14.5 and Python 3.14.7 (python:3-alpine in Docker). Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python and aiohttp are free.