This rule raise an issue if something other than `None` or a valid exception is provided as the cause of an exception chain. == Why is this an issue? Exception chaining enables users to see if an exception is the direct consequence of another exception (see https://peps.python.org/pep-3134/[PEP-3134]). This is useful to propagate the original context of the error. Exceptions are chained using either of the following syntax: * With the `from` keyword [source,python] ---- try: ... except OSError as e: raise RuntimeError("Something went wrong") from e ---- * With the ``++__cause__++`` property [source,python] ---- try: ... except OSError as e: new_exception = RuntimeError("Something went wrong") new_exception.__cause__ = e raise new_exception ---- It is also possible to erase a chaining by setting ``++new_exception.__cause__ = None++`` or using `raise new_exception from None` (see https://peps.python.org/pep-0409/[PEP-409]). Chaining will fail and raise a `TypeError` if something other than `None` or a valid exception, i.e. an instance or a subclass of `BaseException`, is provided. == How to fix it Make sure the cause of a chain of exceptions is either `None` or a valid exception. === Code examples ==== Noncompliant code example [source,python] ---- class A: pass try: raise ValueError("orig") except ValueError as e: new_exc = TypeError("new") new_exc.__cause__ = A() # Noncompliant: A is not a subclass of BaseException. raise new_exc try: raise ValueError("orig") except ValueError as e: raise TypeError("new") from "test" # Noncompliant: "test" is not a valid exception. ---- ==== Compliant solution [source,python] ---- try: raise ValueError("orig") except ValueError as e: new_exc = TypeError("new") new_exc.__cause__ = None # Ok raise new_exc try: raise ValueError("orig") except ValueError as e: new_exc = TypeError("new") new_exc.__cause__ = e # Ok raise new_exc try: raise ValueError("orig") except ValueError as e: raise TypeError("new") from None # Ok try: raise ValueError("orig") except ValueError as e: raise TypeError("new") from e # Ok ---- == Resources === Documentation * https://docs.python.org/3/library/exceptions.html[Built-in Exceptions] === Standards * https://peps.python.org/pep-3134/[Exception Chaining and Embedded Tracebacks] - PEP 3134 * https://peps.python.org/pep-0409/[Suppressing exception context] - PEP 409 * https://peps.python.org/pep-0352/#exception-hierarchy-changes[Required Superclass for Exceptions] - PEP 352 ifdef::env-github,rspecator-view[] ''' == Implementation Specification (visible only on this page) === Message Replace this expression of type X with an exception or None === Highlighting * In a "raise X from Y" statement: ** highlight Y * In an "myexception.__cause__ = Y" statement: ** highlight Y endif::env-github,rspecator-view[]