Course contentsShow
← Rust
Lesson 894 of 1,9107. Error Handling PatternsFree lesson

Handling Unexpected Panics in Middleware

Wrap middleware execution in catch_unwind blocks to prevent process termination.

In this lesson, you will learn how to use catch_unwind to prevent a single panicked request from crashing your entire web server.

When building middleware, you often operate on requests that might trigger unforeseen code paths. If a middleware implementation encounters an unexpected panic—such as an out-of-bounds index or an unwrap() on an empty option—the default behavior in Rust is to unwind the stack and terminate the process. In a production server, this effectively turns a single bad request into a total outage for all users.

To mitigate this, we can wrap our middleware execution in std::panic::catch_unwind. This function allows us to intercept the panic, preventing it from reaching the thread's top level, and instead returning a controlled Result.

Implementing the Safety Wrapper

When applying this to a middleware pattern, you wrap the logic that calls the next service or processes the request body:

use std::panic::{catch_unwind, AssertUnwindSafe};

fn run_middleware_safely<F, R>(middleware_logic: F) -> Result<R, String> 
where 
    F: FnOnce() -> R + std::panic::UnwindSafe 
{
    catch_unwind(AssertUnwindSafe(middleware_logic))
        .map_err(|_| "Middleware panicked: execution aborted to prevent crash".to_string())
}

By wrapping your logic, you gain the ability to catch the panic as a Box<dyn Any + Send>. Instead of allowing the thread to terminate, you can map the error into a standard response—like a 500 Internal Server Error—and log the diagnostic details for later investigation.

Note that catch_unwind only catches unwinding panics. It cannot recover from aborts or non-unwinding panics. Furthermore, you must ensure that any state modified by the middleware is logically sound after a panic; if your middleware leaves a Mutex in a "poisoned" state, you will still need to handle that downstream. Use this sparingly at your application's entry boundaries to ensure your service remains resilient to unpredictable edge cases.

Key Takeaway: Use catch_unwind at the boundaries of your middleware stack to transform catastrophic process-terminating panics into actionable error results.