Skip to content

aiohttp transport retries connection errors even with retry_options attempts=1 #3160

Closed

Description

@JamMaster1999

When aiohttp is installed, the async client retries connection errors once even when retries are disabled through HttpOptions.retry_options.

_async_request_once in google/genai/_api_client.py catches ClientConnectorError, ClientConnectorDNSError, ClientOSError, ServerDisconnectedError and TransportError, sleeps 1–10 seconds, builds a new session and sends the request again. The same block appears twice on main (around lines 1683 and 1761). It doesn't consult retry_options, so HttpRetryOptions(attempts=1) still produces a second request. The httpx path sends exactly one.

This matters for callers that run their own retry and fallback loop. They get an unbudgeted 1–10 second delay, and after a ServerDisconnectedError that happens once the server has received the request, a generation can be sent and billed twice.

Repro (google-genai 2.31.0, Python 3.14)

import asyncio, socket, threading, time
from google import genai
from google.genai import types

posts = 0
def serve(sock):
    global posts
    while True:
        conn, _ = sock.accept()
        if conn.recv(65536).startswith(b"POST"):
            posts += 1
        conn.close()  # drop the connection without a response

sock = socket.socket(); sock.bind(("127.0.0.1", 0)); sock.listen(8)
threading.Thread(target=serve, args=(sock,), daemon=True).start()

async def main():
    client = genai.Client(api_key="test", http_options=types.HttpOptions(
        base_url=f"http://127.0.0.1:{sock.getsockname()[1]}",
        retry_options=types.HttpRetryOptions(attempts=1)))
    t = time.time()
    try:
        await client.aio.models.generate_content(model="gemini-3.5-flash", contents="hi")
    except Exception as e:
        print(type(e).__name__, f"POSTs={posts} after {time.time() - t:.1f}s")

asyncio.run(main())
transport result
aiohttp installed ServerDisconnectedError POSTs=2 after 10.0s
httpx (no aiohttp) ReadError POSTs=1 after 0.1s

Expected

The reconnect respects retry_options: no extra attempt when attempts=1, or the reconnect is folded into the existing tenacity retry so both transports behave the same.

Activity

  1. added
    type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.
    priority: p2Moderately-important priority. Fix may not be included in next release.
    on Oct 19, 2026
  2. Venkaiahbabuneelam commented on Oct 19, 2026

    @Venkaiahbabuneelam

    Hi @JamMaster1999, thank you for the clear bug report and reproduction script!
    We have reproduced this issue where the aiohttp transport in _async_request_once retries connection errors (POSTs=2) even when HttpRetryOptions(attempts=1) is set, and we have escalated it to our engineering team.
    Thanks

  3. added 4 commits that reference this issue on Oct 21, 2026
    c0ac04e
    5b2bcf3
    3dc35c3
    ee639c6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions