Skip to content

Conversation

@fernandocorreia-galileo
Copy link

@fernandocorreia-galileo fernandocorreia-galileo commented Dec 20, 2025

Fixes #880

Problem:

When the retry mechanism re-raises non-retryable exceptions, it explicitly clears the exception chain by using raise final_exc from None. This breaks explicit exception chaining created with raise ... from ..., making the original cause (cause) inaccessible for debugging.

Fix:

Modified _default_exception_factory() in retry_base.py to preserve the __cause__ attribute when re-raising non-retryable exceptions. Instead of returning (exc_list[-1], None), we now return (exc_list[-1], getattr(exc_list[-1], '__cause__', None)).

This ensures that exception chains are maintained through the retry mechanism, preserving debugging information and meeting developer expectations for exception handling.

Testing:

  • Added comprehensive test coverage in test_exception_chain_preservation.py
  • All existing retry tests continue to pass
  • Verified both simple and nested exception chains are preserved

Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:

  • Make sure to open an issue as a bug/issue before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea
  • Ensure the tests and linter pass
  • Code coverage does not decrease (if any source code was changed)
  • Appropriate docs were updated (if necessary)

Fixes #<issue_number_goes_here> 🦕

@product-auto-label product-auto-label bot added the size: m Pull request size is medium. label Dec 20, 2025
@google-cla
Copy link

google-cla bot commented Dec 20, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link

Summary of Changes

Hello @fernandocorreia-galileo, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue where the retry mechanism would inadvertently clear the "cause" attribute of exceptions, breaking explicit exception chaining. By ensuring that the original cause is preserved, the change significantly improves the debuggability and traceability of errors that occur within retryable operations, providing clearer context for why an operation ultimately failed.

Highlights

  • Exception Chaining Preservation: The retry mechanism now correctly preserves the "cause" attribute of exceptions, ensuring that explicit exception chaining (raise ... from ...) is maintained when non-retryable errors are re-raised.
  • New Test Coverage: A new asynchronous test file has been added to specifically verify the preservation of exception chains, covering both single-level and deeply nested exception scenarios within the retry decorator.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes an issue where the exception cause (__cause__) was not being preserved in the retry logic, leading to broken exception chains. The change in google/api_core/retry/retry_base.py ensures that the original cause is carried over when an exception is re-raised. The newly added asynchronous tests in tests/asyncio/retry/test_exception_chain_preservation.py effectively validate this fix for async scenarios.

My review includes a suggestion to simplify the implementation for better readability and a recommendation to add synchronous tests to ensure full coverage of the fix, as the change impacts both sync and async retry mechanisms.

@@ -0,0 +1,155 @@
# Copyright 2025 Google LLC

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These tests are great for verifying the fix for async retries. Since the underlying change in retry_base.py also affects synchronous retries, please consider adding a parallel set of tests for the synchronous case to ensure complete coverage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: m Pull request size is medium.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exception chain lost when retry mechanism re-raises non-retryable errors

1 participant