How to re-raise an exception in nested try/except blocks?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Nested try and except blocks are useful when low level failures must be translated into business level errors. The important part is how you re raise exceptions, because traceback quality determines how quickly you can debug production incidents. In Python, different raise styles change error history, so choosing the right one is critical.
Re Raise Styles and What They Mean
Python gives you three common patterns:
raiseinside anexceptblock: re throws the current exception with original traceback.raise NewError(...) from exc: wraps with domain context and keeps the causal chain.raise NewError(...) from None: hides original cause from output, usually for user facing boundaries.
Preserve Original Traceback with Bare raise
Use bare raise when your current layer cannot add useful context.
Avoid raise exc here. That rethrows but may alter traceback details and confuse debugging.
Add Domain Context with from exc
If your layer can explain business meaning, wrap the low level exception.
Now callers see ConfigLoadError, and the original JSONDecodeError or OSError remains attached in __cause__.
Suppress Internal Details at API Boundary
At a public boundary you may not want to expose internals. Use from None carefully.
Do this only where security or user experience requires hiding internal stack details.
Nested try and except Example
This example shows a realistic multi layer flow.
The chain shows service layer context plus repository context plus root cause.
Logging Without Duplicates
A common issue in nested handling is duplicate logs. If each layer logs at error level and re raises, one failure can generate noisy repeated messages. A better model:
- Intermediate layers add context through exception chaining.
- One boundary layer logs final failure with full traceback.
logger.exception already includes stack trace, so avoid logging the same traceback elsewhere.
Common Pitfalls
- Using
raise excinstead of bareraisewhen preserving traceback. - Catching broad
Exceptiontoo early and hiding specific failure handling. - Wrapping exceptions without
from exc, which breaks causal chain visibility. - Logging at every layer and producing duplicate noisy logs.
- Using
from Nonein internal services where root cause visibility is needed.
Summary
- Use bare
raiseto keep original traceback unchanged. - Use
raise NewError(...) from excto add domain context safely. - Use
from Noneonly at boundaries where internal details must be hidden. - Keep nested handlers purposeful and avoid broad catches without intent.
- Log failures once at a clear boundary to preserve signal quality.

