Jump to solution
Verify

The Fix

Fixes an issue where cookies with duplicate names but different domains or paths were being lost when updating the cookie jar. The root cause was that SimpleCookie uses only the cookie name as its key, causing later cookies with the same name to overwrite earlier ones.

Based on closed aio-libs/aiohttp issue #11105 · PR/commit linked

Production note: This usually shows up under retries/timeouts. Treat it as a side-effect risk until you can verify behavior with a canary + real traffic.

Jump to Verify Open PR/Commit
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@ +Fixed an issue where cookies with duplicate names but different domains or paths +were lost when updating the cookie jar. The :class:`~aiohttp.ClientSession` +cookie jar now correctly stores all cookies even if they have the same name but
repro.py
"""Test script.""" import asyncio import base64 import secrets import orjson from aiohttp import ClientSession # Amazon APP info AMAZON_APP_BUNDLE_ID = "com.amazon.echo" AMAZON_APP_ID = "MAPiOSLib/6.0/ToHideRetailLink" AMAZON_APP_NAME = "AioAmazonDevices" AMAZON_APP_VERSION = "2.2.556530.0" AMAZON_DEVICE_SOFTWARE_VERSION = "35602678" AMAZON_DEVICE_TYPE = "A2IVLV5VM2W81" AMAZON_CLIENT_OS = "16.6" DEFAULT_HEADERS = { "User-Agent": ( f"Mozilla/5.0 (iPhone; CPU iPhone OS {AMAZON_CLIENT_OS.replace('.', '_')} like Mac OS X) " # noqa: E501 "AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" ), "Accept-Language": "en-US", "Accept-Encoding": "gzip", "Connection": "keep-alive", } URL = "https://www.amazon.it/ap/signin" async def main() -> None: """Start script.""" session = ClientSession( headers=DEFAULT_HEADERS, cookies=await _build_init_cookies(), ) resp = await session.request("POST", URL) print("Cookies:") print(resp.cookies) print("--------") print("Headers:") print(resp.headers) async def _build_init_cookies() -> dict[str, str]: """Build initial cookies to prevent captcha in most cases.""" token_bytes = secrets.token_bytes(313) frc = base64.b64encode(token_bytes).decode("ascii").rstrip("=") map_md_dict = { "device_user_dictionary": [], "device_registration_data": { "software_version": AMAZON_DEVICE_SOFTWARE_VERSION, }, "app_identifier": { "app_version": AMAZON_APP_VERSION, "bundle_id": AMAZON_APP_BUNDLE_ID, }, } map_md_str = orjson.dumps(map_md_dict).decode("utf-8") map_md = base64.b64encode(map_md_str.encode()).decode().rstrip("=") return {"amzn-app-id": AMAZON_APP_ID, "frc": frc, "map-md": map_md} if __name__ == "__main__": asyncio.run(main())
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
Option A — Apply the official fix\nFixes an issue where cookies with duplicate names but different domains or paths were being lost when updating the cookie jar. The root cause was that SimpleCookie uses only the cookie name as its key, causing later cookies with the same name to overwrite earlier ones.\nWhen NOT to use: This fix should not be used if maintaining backward compatibility with existing cookie handling is critical.\n\n

Why This Fix Works in Production

  • Trigger: ```python-traceback
  • Mechanism: Cookies with duplicate names but different domains or paths were lost when updating the cookie jar due to SimpleCookie's behavior
Production impact:
  • If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).

Why This Breaks in Prod

  • Shows up under Python 3.13.3 in real deployments (not just unit tests).
  • Cookies with duplicate names but different domains or paths were lost when updating the cookie jar due to SimpleCookie's behavior
  • Production symptom (often without a traceback): ```python-traceback

Proof / Evidence

Discussion

High-signal excerpts from the issue thread (symptoms, repros, edge-cases).

“We could wrap SimpleCookie with something like this to return all the cookies... but I don't think that is what you want. I think the…”
@bdraco · 2025-05-31 · source
“I think the solution you want is to update cookie parsing to prefer Secure cookies over non-secure in HTTPS”
@bdraco · 2025-05-31 · source
“the problem is we are storing cookies in SimpleCookie which doesn't support multiple cookies with the same name”
@bdraco · 2025-05-31 · source
“According to RFC 6265, multiple cookies with the same name, domain, and path, the most recently received cookie overwrites the previous one in the cookie…”
@bdraco · 2025-05-31 · source

Failure Signature (Search String)

  • ```python-traceback
  • the problem is we are storing cookies in SimpleCookie which doesn't support multiple cookies with the same name
Copy-friendly signature
signature.txt
Failure Signature ----------------- ```python-traceback the problem is we are storing cookies in SimpleCookie which doesn't support multiple cookies with the same name

Error Message

Signature-only (no traceback captured)
error.txt
Error Message ------------- ```python-traceback the problem is we are storing cookies in SimpleCookie which doesn't support multiple cookies with the same name

Minimal Reproduction

repro.py
"""Test script.""" import asyncio import base64 import secrets import orjson from aiohttp import ClientSession # Amazon APP info AMAZON_APP_BUNDLE_ID = "com.amazon.echo" AMAZON_APP_ID = "MAPiOSLib/6.0/ToHideRetailLink" AMAZON_APP_NAME = "AioAmazonDevices" AMAZON_APP_VERSION = "2.2.556530.0" AMAZON_DEVICE_SOFTWARE_VERSION = "35602678" AMAZON_DEVICE_TYPE = "A2IVLV5VM2W81" AMAZON_CLIENT_OS = "16.6" DEFAULT_HEADERS = { "User-Agent": ( f"Mozilla/5.0 (iPhone; CPU iPhone OS {AMAZON_CLIENT_OS.replace('.', '_')} like Mac OS X) " # noqa: E501 "AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" ), "Accept-Language": "en-US", "Accept-Encoding": "gzip", "Connection": "keep-alive", } URL = "https://www.amazon.it/ap/signin" async def main() -> None: """Start script.""" session = ClientSession( headers=DEFAULT_HEADERS, cookies=await _build_init_cookies(), ) resp = await session.request("POST", URL) print("Cookies:") print(resp.cookies) print("--------") print("Headers:") print(resp.headers) async def _build_init_cookies() -> dict[str, str]: """Build initial cookies to prevent captcha in most cases.""" token_bytes = secrets.token_bytes(313) frc = base64.b64encode(token_bytes).decode("ascii").rstrip("=") map_md_dict = { "device_user_dictionary": [], "device_registration_data": { "software_version": AMAZON_DEVICE_SOFTWARE_VERSION, }, "app_identifier": { "app_version": AMAZON_APP_VERSION, "bundle_id": AMAZON_APP_BUNDLE_ID, }, } map_md_str = orjson.dumps(map_md_dict).decode("utf-8") map_md = base64.b64encode(map_md_str.encode()).decode().rstrip("=") return {"amzn-app-id": AMAZON_APP_ID, "frc": frc, "map-md": map_md} if __name__ == "__main__": asyncio.run(main())

Environment

  • Python: 3.13.3

Why It Broke

Cookies with duplicate names but different domains or paths were lost when updating the cookie jar due to SimpleCookie's behavior

Fix Options (Details)

Option A — Apply the official fix

Fixes an issue where cookies with duplicate names but different domains or paths were being lost when updating the cookie jar. The root cause was that SimpleCookie uses only the cookie name as its key, causing later cookies with the same name to overwrite earlier ones.

When NOT to use: This fix should not be used if maintaining backward compatibility with existing cookie handling is critical.

Fix reference: https://github.com/aio-libs/aiohttp/pull/11106

Last verified: 2026-02-09. Validate in your environment.

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • This fix should not be used if maintaining backward compatibility with existing cookie handling is critical.

Verify Fix

verify
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.