The Fix
Adds support for using absolute URLs to override the base URL in ClientSession, resolving the AssertionError when using WSS URLs.
Based on closed aio-libs/aiohttp issue #10027 · PR/commit linked
Production note: Most teams hit this during upgrades or environment changes. Roll out with a canary and smoke critical endpoints (health, OpenAPI/docs) before 100%.
@@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
+Added support for overriding the base URL with an absolute one in client sessions
+-- by :user:`vivodi`.
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
from aiohttp import ClientSession
from asyncio import run
from typing import *
class DiscordWebSocket:
session = lambda: ClientSession(base_url = "https://discord.com/api/v10/")
connection = None # would likely be replaced by DiscordWebSocket.connect()
@classmethod
async def connect(cls) -> NoReturn:
wss : Dict = await cls.get("gateway") # {"url": "wss://gateway.discord.gg"}
async with cls.session() as session:
response = await session.ws_connect(f"{wss['url']}/") # AssertionError
return response # debug stuff lol
@classmethod
async def get(cls, endpoint : str) -> Dict:
async with cls.session() as session:
response = session.get(endpoint)
return await response.json()
async def main() -> NoReturn:
print(f"{await DiscordWebSocket.connect() = }")
run(main())
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Apply the official fix\nAdds support for using absolute URLs to override the base URL in ClientSession, resolving the AssertionError when using WSS URLs.\nWhen NOT to use: This fix is not applicable if the base URL should not be overridden by absolute URLs.\n\n
Why This Fix Works in Production
- Trigger: AssertionError
- Mechanism: The assertion fails because an absolute URL is passed while a base URL is set in ClientSession
- If left unfixed, the same config can fail only in production (env differences), causing startup failures or partial feature outages.
Why This Breaks in Prod
- Shows up under Python 3.12 in real deployments (not just unit tests).
- The assertion fails because an absolute URL is passed while a base URL is set in ClientSession
- Surfaces as: File "...\aiohttp\client.py", line 467, in _build_url
Proof / Evidence
- GitHub issue: #10027
- Fix PR: https://github.com/aio-libs/aiohttp/pull/10074
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.70
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.33
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“> The url in ws_connect() must be relative if base_url is set in ClientSession. Passing a absolute url in request calls to override base_url is…”
“> Passing a absolute url in request calls to override base_url is not supported”
“The url in ws_connect() must be relative if base_url is set in ClientSession. Passing a absolute url in request calls to override base_url is not…”
“> As a side note, the type annotations with this are incorrect in the example. The NoReturn means that they should hang forever. But main()…”
Failure Signature (Search String)
- AssertionError
Error Message
Stack trace
Error Message
-------------
File "...\aiohttp\client.py", line 467, in _build_url
assert not url.absolute
^^^^^^^^^^^^^^^^^
AssertionError
Stack trace
Error Message
-------------
python .\main.py
Traceback (most recent call last):
File "C:\Users\demo\OneDrive\Documents\python\test\main.py", line 32, in <module>
run(main())
File "C:\Users\demo\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "C:\Users\demo\AppData\Local\Programs\Python\Python312\Lib\asyncio\runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\demo\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 687, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "C:\Users\demo\OneDrive\Documents\python\test\main.py", line 29, in main
print(f"{await WebSocket.connect() = }")
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\demo\OneDrive\Documents\python\test\main.py", line 16, in connect
response = await session.ws_connect(str(URL(f"{wss['url']}/")))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\demo\AppData\Local\Programs\Python\Python312\Lib\site-packages\aiohttp\client.py", line 1002, in _ws_connect
resp = await self.request(
^^^^^^^^^^^^^^^^^^^
File "C:\Users\demo\AppData\Local\Programs\Python\Python312\Lib\site-packages\aiohttp\client.py", line 535, in _request
url = self._buil
... (truncated) ...
Minimal Reproduction
from aiohttp import ClientSession
from asyncio import run
from typing import *
class DiscordWebSocket:
session = lambda: ClientSession(base_url = "https://discord.com/api/v10/")
connection = None # would likely be replaced by DiscordWebSocket.connect()
@classmethod
async def connect(cls) -> NoReturn:
wss : Dict = await cls.get("gateway") # {"url": "wss://gateway.discord.gg"}
async with cls.session() as session:
response = await session.ws_connect(f"{wss['url']}/") # AssertionError
return response # debug stuff lol
@classmethod
async def get(cls, endpoint : str) -> Dict:
async with cls.session() as session:
response = session.get(endpoint)
return await response.json()
async def main() -> NoReturn:
print(f"{await DiscordWebSocket.connect() = }")
run(main())
Environment
- Python: 3.12
What Broke
The application raises an AssertionError when trying to connect to a WSS URL.
Why It Broke
The assertion fails because an absolute URL is passed while a base URL is set in ClientSession
Fix Options (Details)
Option A — Apply the official fix
Adds support for using absolute URLs to override the base URL in ClientSession, resolving the AssertionError when using WSS URLs.
Fix reference: https://github.com/aio-libs/aiohttp/pull/10074
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- This fix is not applicable if the base URL should not be overridden by absolute URLs.
Verify Fix
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Did This Fix Work in Your Case?
Quick signal helps us prioritize which fixes to verify and improve.
Prevention
- Capture the exact failing error string in logs and tests so you can reproduce via a minimal script.
- Pin production dependencies and upgrade only with a reproducible test that hits the failing path.
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.