You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 23, 2026. It is now read-only.
The retry mechanism clears the __cause__ attribute when re-raising non-retryable exceptions, breaking explicit exception chaining created with raise ... from ....
Steps to reproduce
Use the @retry_async.AsyncRetry decorator
Raise a non-retryable exception with a cause
Catch the exception and try to read or log its cause
In retry_base.py:168, _default_exception_factory() returns (exc_list[-1], None), which causes raise final_exc from None on line 214, explicitly clearing __cause__.
Proposed fix
Preserve the exception's cause attribute:
# Beforereturnexc_list[-1], None# Afterfinal_exc=exc_list[-1]
cause=getattr(final_exc, '__cause__', None)
returnfinal_exc, cause
This maintains exception chains for better debugging and meets developer expectations for exception handling.
Environment details
google-api-coreversion: HEAD = f8bf6f9610f3e0e7580f223794c3906513e1fa73Description
The retry mechanism clears the
__cause__attribute when re-raising non-retryable exceptions, breaking explicit exception chaining created withraise ... from ....Steps to reproduce
@retry_async.AsyncRetrydecoratorCode example
See https://github.com/googleapis/python-api-core/pull/879/changes for a unit test that fails with the current code and passes with the proposed fix.
Root Cause
In retry_base.py:168,
_default_exception_factory()returns(exc_list[-1], None), which causes raisefinal_excfromNoneon line 214, explicitly clearing__cause__.Proposed fix
Preserve the exception's cause attribute:
This maintains exception chains for better debugging and meets developer expectations for exception handling.
Draft pull request
#879