Skip to content

[BUG] Traceback __notes__ from outermost exception shown on all exceptions in chain #3960

Description

@reteps

Description

When displaying a chained exception where only the outermost exception has __notes__ (via PEP 678 add_note), Rich incorrectly displays those notes on every exception in the chain, not just the one that has them. Investigation done by Claude.

Minimal reproduction

from rich.console import Console

try:
    try:
        raise ValueError("original error")
    except ValueError as exc:
        raise RuntimeError("wrapped error") from exc
except RuntimeError as exc:
    exc.add_note("This note was added to RuntimeError only")
    Console(width=80).print_exception()

Rich output (note appears on both exceptions):

ValueError: original error
[NOTE] This note was added to RuntimeError only    <-- should not be here

The above exception was the direct cause of the following exception:

RuntimeError: wrapped error
[NOTE] This note was added to RuntimeError only    <-- correct

Python native output (note appears only on RuntimeError, as expected):

ValueError: original error

The above exception was the direct cause of the following exception:

RuntimeError: wrapped error
This note was added to RuntimeError only

Cause

In Traceback.extract(), the notes are read once from the initial exc_value before the while True loop, then the same list is reused for every Stack in the chain:

notes: List[str] = getattr(exc_value, "__notes__", None) or []  # read once

while True:
    stack = Stack(
        ...
        notes=notes,  # same reference for ALL stacks
    )
    # ... walks __cause__ / __context__ chain ...

The fix would be to read notes from each exc_value inside the loop:

while True:
    notes: List[str] = getattr(exc_value, "__notes__", None) or []
    stack = Stack(
        ...
        notes=notes,
    )

Environment

  • Rich 14.3.2
  • Python 3.13

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions