Repository navigation
Description
Describe the bug
When HttpRetryOptions is configured and aiohttp is used as the async HTTP transport (google-genai[aiohttp]), request timeouts and wrapped google.auth.aio transport exceptions bypass retry_args() and fail on the first attempt without retrying.
Specifically:
asyncio.TimeoutError(andaiohttp.ServerTimeoutError/aiohttp.ConnectionTimeoutError):
While_HTTPX_TRANSIENT_EXCincludeshttpx.TimeoutExceptionandhttpx2.TimeoutException(added in fix(retry): retry on httpx.TimeoutException with HttpRetryOptions #2345 for httpx.TimeoutException is not retried despite HttpRetryOptions being configured #2337),_AIOHTTP_TRANSIENT_EXConly lists(aiohttp.ClientConnectorError, aiohttp.ClientOSError, aiohttp.ServerDisconnectedError). Inaiohttp,ClientTimeout(total=...)(TimerContext.__exit__) raisesasyncio.TimeoutErrordirectly, andaiohttp.ServerTimeoutError/ConnectionTimeoutErrorinherit from(aiohttp.ClientConnectionError, asyncio.TimeoutError), notClientConnectorError,ClientOSError, orServerDisconnectedError.google.auth.exceptions.TimeoutError(auth_exceptions.TimeoutError):
When Vertex AI mTLS is used (_use_google_auth_async() == True),_get_aiohttp_session()returnsgoogle.auth.aio.transport.sessions.AsyncAuthorizedSession. Bothgoogle.auth.aio.transport.aiohttp.Request.__call__andgoogle.auth.aio.transport.sessions.timeout_guardcatchasyncio.TimeoutErrorand raisegoogle.auth.exceptions.TimeoutError(which inherits fromGoogleAuthError, notbuiltins.TimeoutErrororaiohttp.ClientError).google.auth.exceptions.TransportErrorwrapping_AIOHTTP_TRANSIENT_EXC:
UnderAsyncAuthorizedSession,google.auth.aio.transport.aiohttp.Request.__call__catchesaiohttp.ClientErrorand raisesgoogle.auth.exceptions.TransportError(...) from caught_exc. In_async_request_once(), theexcept (..., auth_exceptions.TransportError)block re-raises whenretry_optionsis configured (raise # HttpRetryOptions owns retries; tenacity decides.), butretry_args()does not matchauth_exceptions.TransportErrorwrapping_AIOHTTP_TRANSIENT_EXC.
Steps to reproduce
import asyncio
from google.auth import exceptions as auth_exceptions
from google.genai import _api_client as api_client
from google.genai import types
import aiohttp
retry = api_client.retry_args(types.HttpRetryOptions())['retry']
print("asyncio.TimeoutError retried:", retry.predicate(asyncio.TimeoutError()))
print("aiohttp.ServerTimeoutError retried:", retry.predicate(aiohttp.ServerTimeoutError()))
print("google.auth.exceptions.TimeoutError retried:", retry.predicate(auth_exceptions.TimeoutError("Request timed out")))Output on main:
asyncio.TimeoutError retried: False
aiohttp.ServerTimeoutError retried: False
google.auth.exceptions.TimeoutError retried: False
Expected behavior
When HttpRetryOptions is configured, retry_args() should retry asyncio.TimeoutError (including aiohttp.ServerTimeoutError and aiohttp.ConnectionTimeoutError), google.auth.exceptions.TimeoutError, and google.auth.exceptions.TransportError whose __cause__ is in _AIOHTTP_TRANSIENT_EXC, matching the httpx.TimeoutException behavior from #2337 / #2345 while keeping non-transient errors (such as aiohttp.ClientPayloadError and google.auth.exceptions.RefreshError) and the no-retry_options path unchanged.
Activity
fix: Retry aiohttp timeouts and wrapped google-auth transport errors …
Venkaiahbabuneelam commentedon Nov 11, 2026
Hi @rladeira, Thanks for reaching out us!
I have successfully reproduced the issue when HttpRetryOptions is enabled in google-genai, async requests using aiohttp and google-auth token refreshes do not retry when a timeout or temporary aiohttp disconnect happens because _api_client.py is missing those timeout/error types in its retry list, causing the request to fail immediately on the first try, we will file a bug internally.
Thanks
fix: Retry aiohttp timeouts and wrapped google-auth transport errors …