Skip to content

fix: preserve original exception context in retry decorator#8832

Open
dreamcreated wants to merge 3 commits intoaws:developfrom
dreamcreated:fix/retry-preserve-exception-context
Open

fix: preserve original exception context in retry decorator#8832
dreamcreated wants to merge 3 commits intoaws:developfrom
dreamcreated:fix/retry-preserve-exception-context

Conversation

@dreamcreated
Copy link

@dreamcreated dreamcreated commented Mar 19, 2026

Problem

The retry decorator in samcli/lib/utils/retry.py swallows the original exception when all retries are exhausted. This makes it impossible to diagnose the root cause of failures because the original traceback is lost.

Before this fix:

while remaining_attempts >= 1:
    try:
        return func(*args, **kwargs)
    except exc:
        ...
raise exc_raise(exc_raise_msg)  # original exception context lost

Fix

Capture the last exception and chain it using raise ... from last_exception:

last_exception = None
while remaining_attempts >= 1:
    try:
        return func(*args, **kwargs)
    except exc as e:
        last_exception = e
        ...
raise exc_raise(exc_raise_msg) from last_exception

This preserves the original traceback via Python exception chaining (__cause__), making it much easier to diagnose the root cause of failures.

Testing

The change is backwards-compatible — the raised exception type and message remain the same, only the __cause__ is now populated.

Related

When all retry attempts are exhausted, the decorator previously raised
exc_raise(exc_raise_msg) without chaining the original exception, making
it impossible to diagnose the root cause from the traceback.

Fix: capture the last caught exception and chain it using
'raise ... from last_exception' so Python's exception chaining
(__cause__) is preserved in the traceback.

Fixes: bnusunny#29
@dreamcreated dreamcreated requested a review from a team as a code owner March 19, 2026 02:12
@github-actions github-actions bot added pr/external stage/needs-triage Automatically applied to new issues and PRs, indicating they haven't been looked at. labels Mar 19, 2026
@seshubaws
Copy link
Contributor

@dreamcreated Thank you for raising this! You said "Fixes #29" but I think that may be a typo, what issue does this fix? Just so we can link it properly

@dreamcreated
Copy link
Author

Hi @seshubaws, thank you for pointing that out! Yes, that was a typo — the original issue report is in the fork at bnusunny#29 (a good-first-issue tracking the same problem). The upstream aws/aws-sam-cli does not have a separate tracking issue for this, but the fix addresses the same bug described there.

The core problem: the retry decorator loses the original exception traceback by raising exc_raise(exc_raise_msg) without chaining it, which makes debugging failures very difficult. The one-line fix raise exc_raise(exc_raise_msg) from last_exception preserves the full traceback via Python exception chaining (__cause__).

Happy to open a dedicated tracking issue on aws/aws-sam-cli if that helps your process!

@vicheey
Copy link
Contributor

vicheey commented Mar 26, 2026

Thanks for this fix @dreamcreated,

I traced the git history — the original retry.py was written in 2020 by @awood45 for Lambda Extensions support, and the missing exception chaining was a miss.

Code looks good.

@vicheey vicheey added type/bug and removed stage/needs-triage Automatically applied to new issues and PRs, indicating they haven't been looked at. type/bug labels Mar 26, 2026
@bnusunny
Copy link
Contributor

@dreamcreated please also add a unit test in the PR.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants