GeezerVison is showing github.com — `ExceptionGroup` repr is misleading if original exception sequence is mutated · Issue #141732 · python/cpython
ExceptionGroup repr is misleading if original exception sequence is mutated #141732
Labels interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DescriptionBug report
Bug description:
The exception listing in repr(exc_grp) diverges from exc_grp.exceptions when the initial sequence of exceptions passed to the constructor has been mutated.
Expected behavior: The exceptions listed in repr(exc_grp) match exc_grp.exceptions, which is immutable.
Reproducer:
exceptions = list[Exception]()
exceptions.append(ValueError())
exc_grp = ExceptionGroup("", exceptions)
print(f"{exc_grp.exceptions=!r}")
print(f"{exc_grp=!r}")
print()
exceptions.clear()
print(f"{exc_grp.exceptions=!r}")
print(f"{exc_grp=!r}")
Output:
exc_grp.exceptions=(ValueError(),)
exc_grp=ExceptionGroup('', [ValueError()])
exc_grp.exceptions=(ValueError(),)
exc_grp=ExceptionGroup('', [])
Expected output:
exc_grp.exceptions=(ValueError(),)
exc_grp=ExceptionGroup('', [ValueError()])
exc_grp.exceptions=(ValueError(),)
exc_grp=ExceptionGroup('', [ValueError()])
CPython versions tested on:
3.11, 3.12, 3.13, 3.14
Operating systems tested on:
Linux
Linked PRs
Activitygschaffner commented on Nov 19, 2025 I noticed that PyPy behaves the way I expected here; they use self.exceptions in BaseExceptionGroup.__repr__ instead of self.args[1]:
https://github.com/pypy/pypy/blob/release-pypy3.11-v7.3.20/pypy/module/exceptions/app_group.py#L92-L93
On CPython, it looks like BaseExceptionGroup.__repr__ resolves to BaseException.__repr__, so the repr ends up using self.args[1] instead of self.exceptions.
I skimmed the PEP and didn't see anything that indicated that either repr implementation is in violation of the PEP. dr-carlos commented on Nov 19, 2025
I skimmed the PEP and didn't see anything that indicated that either repr implementation is in violation of the PEP.
The PEP does reference the repr() of ExceptionGroups but not explicitly specify anything:
>>> try:
... raise ExceptionGroup("problem", [BlockingIOError()])
... except* OSError as e: # Would catch the error
... print(repr(e))
... except* BlockingIOError: # Would never run
... print('never')
...
ExceptionGroup('problem', [BlockingIOError()])
But I agree that mutating an argument which is only used to create an immutable tuple shouldn't change the repr. Reacted by Ganden Schaffner serhiy-storchaka commented on Nov 19, 2025 This may be a part of more complex problem. See #137889. Reacted by dr-carlos and Ganden Schaffner added a commit that references this issue on Dec 7, 2025gh-141732: Fix `ExceptionGroup` repr changing when original exception… hugovk commented on Feb 3, 2026 This has been merged in main and 3.13 but cannot be merged for 3.14 because of failing CI: #142388.
Please can you check the backport? dr-carlos commented on Feb 3, 2026
This has been merged in main and 3.13 but cannot be merged for 3.14 because of failing CI: #142388.
Please can you check the backport?
Yes, will do!
Opened #144445
MetadataMetadatainterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DevelopmentNo branches or pull requestsIssue actions
|