aiohttp timeout and wrapped google-auth transport exceptions are not retried despite HttpRetryOptions being configured

未關閉
#3,329 1 則留言 0 個 reaction 已指派 1 人 在 GitHub 檢視

維護者通常 1 天內回覆

@Venkaiahbabuneelam 已經在處理了。

開始於 2026年11月11日。

  • #3330 來自 @rladeira —— 未關閉
  • #3332 來自 @copybara-service —— 未關閉

評估

難度
3/5
預估耗時
1-2 天
新手友好度
72/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
活躍
技術堆疊
python
領域
api, backend

研究方向

Start in google/genai/_api_client.py at retry_args() and _AIOHTTP_TRANSIENT_EXC, then trace _async_request_once() to understand how authenticated transport exceptions are handled. Reproduce the listed predicates and add coverage for the timeout and wrapped transport cases, while checking that payload and refresh errors remain non-retryable and the no-retry_options path is unchanged.

由索引模型根據 Issue 內容生成。

描述

priority: p2 type: bug
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:

  1. asyncio.TimeoutError (and aiohttp.ServerTimeoutError / aiohttp.ConnectionTimeoutError):
    While _HTTPX_TRANSIENT_EXC includes httpx.TimeoutException and httpx2.TimeoutException (added in #2345 for #2337), _AIOHTTP_TRANSIENT_EXC only lists (aiohttp.ClientConnectorError, aiohttp.ClientOSError, aiohttp.ServerDisconnectedError). In aiohttp, ClientTimeout(total=...) (TimerContext.__exit__) raises asyncio.TimeoutError directly, and aiohttp.ServerTimeoutError / ConnectionTimeoutError inherit from (aiohttp.ClientConnectionError, asyncio.TimeoutError), not ClientConnectorError, ClientOSError, or ServerDisconnectedError.
  2. google.auth.exceptions.TimeoutError (auth_exceptions.TimeoutError):
    When Vertex AI mTLS is used (_use_google_auth_async() == True), _get_aiohttp_session() returns google.auth.aio.transport.sessions.AsyncAuthorizedSession. Both google.auth.aio.transport.aiohttp.Request.__call__ and google.auth.aio.transport.sessions.timeout_guard catch asyncio.TimeoutError and raise google.auth.exceptions.TimeoutError (which inherits from GoogleAuthError, not builtins.TimeoutError or aiohttp.ClientError).
  3. google.auth.exceptions.TransportError wrapping _AIOHTTP_TRANSIENT_EXC:
    Under AsyncAuthorizedSession, google.auth.aio.transport.aiohttp.Request.__call__ catches aiohttp.ClientError and raises google.auth.exceptions.TransportError(...) from caught_exc. In _async_request_once(), the except (..., auth_exceptions.TransportError) block re-raises when retry_options is configured (raise # HttpRetryOptions owns retries; tenacity decides.), but retry_args() does not match auth_exceptions.TransportError wrapping _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.

主要語言
Python
星號
4.1k
分支
1.1k
平均合併
1 天 20 小時
30 天內合併 PR
90

環境準備

  • 沒有 Dockerfile 或 Docker Compose 檔案
  • 沒有 Pull Request 範本
  • 閱讀貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

googleapis/python-genai 的其他 Issue

查看 googleapis/python-genai 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。