Exercise 3: Catching Two Real Exception Types — Possible Solution ==================================================================== THE EXTENDED MIDDLEWARE ------------------------------ class NotFoundError(Exception): pass def error_handling_middleware(request, next): try: return next(request) except NotFoundError as e: return Response(f"404 Not Found: {e}") except ValueError as e: return Response(f"500 Internal Server Error: {e}") A second except clause, matching the chapter's own single-exception pattern exactly, just with NotFoundError checked first. Python tries except clauses in the order they're written, top to bottom, and stops at the first one whose exception type matches -- so NotFoundError needs its own clause ahead of (or instead of overlapping with) ValueError's, which it does here since the two are unrelated exception types. TWO REAL CRASHING HANDLERS ------------------------------ def crashing_handler_value(request): raise ValueError("something genuinely went wrong") def crashing_handler_notfound(request): raise NotFoundError("no such resource") app_a = build_chain([error_handling_middleware], crashing_handler_value) app_b = build_chain([error_handling_middleware], crashing_handler_notfound) RESULTS, VERIFIED DIRECTLY ------------------------------ ValueError case: 500 Internal Server Error: something genuinely went wrong NotFoundError case: 404 Not Found: no such resource The identical middleware, wrapping two genuinely different handlers, correctly routes each real exception to its own distinct response -- a ValueError still produces the chapter's own original 500 response unchanged, and the new NotFoundError produces a real, distinct 404 response, confirming the new except clause didn't accidentally shadow or interfere with the original one. WHY THIS WORKS AS AN ANSWER ---------------------------- It extends the chapter's own real error-handling pattern with a second, genuinely distinct exception type rather than a cosmetic variation of the same one, and verifies both code paths independently against two separate real handlers -- confirming the original ValueError behavior survived unchanged alongside the new NotFoundError behavior, not just that the new case alone works.