Skip to content

[BUG] Rich enters infinite loop in certain cases when printing exceptions #3708

@chovanecadam

Description

@chovanecadam

Describe the bug

console.print_exception will enter an infinite loop when exc.__cause__ is exc. This can happen if we raise exc from exc. Here is the minimal example. Python enters infinite loop eating all resources until killed.

from rich.console import Console

console = Console()


def foo() -> None:
    try:
        raise RuntimeError("Hello")
    except Exception as e:
        raise e from e

def bar():
    try:
        foo()
    except Exception as e:
        assert e is e.__cause__
        console.print_exception(show_locals=True)

bar()

I suspect the culprit is here:

rich/rich/traceback.py

Lines 564 to 572 in 0c6c756

cause = getattr(exc_value, "__cause__", None)
if cause:
exc_type = cause.__class__
exc_value = cause
# __traceback__ can be None, e.g. for exceptions raised by the
# 'multiprocessing' module
traceback = cause.__traceback__
is_cause = True
continue

I image the patch to look smth like this, but I am not familiar with the codebase. I am not sure if the same can happen with the __context__ attribute a few lines below the snippet above.

            cause = getattr(exc_value, "__cause__", None)
-            if cause:
+            if cause and cause is not exc_value:
                exc_type = cause.__class__
                exc_value = cause
                # __traceback__ can be None, e.g. for exceptions raised by the
                # 'multiprocessing' module
                traceback = cause.__traceback__
                is_cause = True
                continue

Now I know that raise exc from exc does not make sense and should just be raise exc. But nevertheless, Rich should handle this case as well and not loop forever until it eats the whole RAM. Some python libraries unfortunately use raise exc from exc and fixing all of them is not a viable option.

I am using the latest release of Rich with Python 3.13.3

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions