How to Re-raise Exceptions with 'raise from' in Python

Shows how to re-raise an exception with explicit context chaining using the 'raise ... from ...' syntax, so the original cause is preserved for debugging.

Medium Python 3.9+ Aug 9, 2026 Errors & debugging 12 views 0 copies

Python code

17 lines
Python 3.9+
def divide_with_chain(a, b):
    try:
        result = a / b
        return result
    except ZeroDivisionError as original_error:
        # Re-raise with explicit chaining context
        raise ValueError("Cannot divide by zero") from original_error

def explain_chain():
    try:
        divide_with_chain(10, 0)
    except ValueError as final_error:
        print(f"Caught: {final_error}")
        print(f"Original cause: {final_error.__cause__}")

if __name__ == "__main__":
    explain_chain()

Output

stdout
Caught: Cannot divide by zero
Original cause: division by zero

How it works

Using raise ValueError(...) from original_error creates an implicit exception chain linking the new exception to the original one. The __cause__ attribute on the new exception stores the original error, preserving the full traceback context. This pattern is useful when you want to wrap low-level errors with more meaningful, domain-specific messages without losing the root cause. The from clause is what sets __cause__; without it, the original error may still be available via __context__, but it's less explicit. This makes debugging production issues significantly easier because you can see the chain from the top-level error back to its root.

Common mistakes

  • Raising a new exception without 'from' and losing the original traceback context
  • Using 'raise' alone inside an except block, which only re-raises the same exception instead of wrapping it
  • Accessing `__cause__` when no `from` clause was used, resulting in None

Variations

  1. Use `raise ValueError("Cannot divide by zero") from None` to suppress implicit chaining when you want to hide the original cause
  2. Chain multiple levels by wrapping exceptions again in nested try/except blocks

Real-world use cases

  • Flask or FastAPI handlers that wrap database errors into HTTP exceptions while preserving the underlying SQL error for logs.
  • ETL scripts that convert parsing errors into contextual errors with the original file/line details for the logs.
  • CLI tools that translate low-level library errors into user-friendly messages while keeping full traceback info in the logs.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Errors & debugging

Related tutorials and quizzes for this topic.