---
title: Use raise...from to Chain Exceptions
impact: MEDIUM
impactDescription: Rethrowing an exception without raise...from loses the original traceback, making it impossible to diagnose the root cause in production logs.
tags: python, exceptions, error-handling, traceability, quality
---

## Use raise...from to Chain Exceptions

When catching an exception and raising a different (or more specific) one, use `raise NewException("msg") from original_exception` to preserve the full causal chain. Without `from`, Python 3 still shows an implicit chain, but the context can be confusing. Using `from` makes the chain explicit and intentional.

Using `raise ... from None` deliberately suppresses the original context when it adds no value to the end user.

**Incorrect:**
```python
import json

def load_config(path: str) -> dict:
    try:
        with open(path, encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError:
        raise ValueError("Config file is malformed")  # original traceback lost

def get_user(user_id: int) -> dict:
    try:
        return db.find_by_id(user_id)
    except DatabaseError:
        raise RuntimeError("Failed to fetch user")  # loses DB error context
```

**Correct:**
```python
import json

def load_config(path: str) -> dict:
    try:
        with open(path, encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        raise ValueError(f"Config file '{path}' is malformed") from e  # chain preserved

def get_user(user_id: int) -> dict:
    try:
        return db.find_by_id(user_id)
    except DatabaseError as e:
        raise UserNotFoundError(f"User {user_id} could not be fetched") from e

# Suppress context intentionally (e.g., to hide internal DB details from callers)
def validate_token(token: str) -> None:
    try:
        jwt.decode(token, SECRET)
    except jwt.ExpiredSignatureError:
        raise AuthenticationError("Token has expired") from None
```

**Tools:** Ruff `W0707` / `raise-missing-from`, `TRY200` (reraise-no-cause), `B904` (raise-without-from-inside-except), Pylint `W0707`, flake8-bugbear
