Repository navigation
Description
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
feat: run every provider's SDK on aiohttp
feat: run every provider's SDK on aiohttp
feat: run every provider's SDK on aiohttp
Venkaiahbabuneelam commentedon Oct 19, 2026
Hi @JamMaster1999, thank you for the clear bug report and reproduction script!
We have reproduced this issue where the
aiohttptransport in_async_request_onceretries connection errors (POSTs=2) even whenHttpRetryOptions(attempts=1)is set, and we have escalated it to our engineering team.Thanks
fix: Honor HttpRetryOptions for aiohttp connection errors in async re…
fix: Honor HttpRetryOptions for aiohttp connection errors in async re…
fix: Honor HttpRetryOptions for aiohttp connection errors in async re…
fix: Honor HttpRetryOptions for aiohttp connection errors in async re…