tokio-rs/tokio · error · syn::Error

The `unhandled_panic` option requires the `current_thread` r

Error message

The `unhandled_panic` option requires the `current_thread` runtime flavor. Use `#[{}(flavor = "current_thread")]`

What it means

In `build` (entry.rs:233), `unhandled_panic` policy is only honored by the `current_thread` runtime. Setting it together with `flavor = "multi_thread"` is rejected and the user is pointed to `current_thread`.

Source

Thrown at tokio-macros/src/entry.rs:234

            }
        };

        let start_paused = match (flavor, self.start_paused) {
            (F::Threaded, Some((_, start_paused_span))) => {
                let msg = format!(
                    "The `start_paused` option requires the `current_thread` runtime flavor. Use `#[{}(flavor = \"current_thread\")]`",
                    self.macro_name(),
                );
                return Err(syn::Error::new(start_paused_span, msg));
            }
            (F::CurrentThread | F::Local, Some((start_paused, _))) => Some(start_paused),
            (_, None) => None,
        };

        let unhandled_panic = match (flavor, self.unhandled_panic) {
            (F::Threaded, Some((_, unhandled_panic_span))) => {
                let msg = format!(
                    "The `unhandled_panic` option requires the `current_thread` runtime flavor. Use `#[{}(flavor = \"current_thread\")]`",
                    self.macro_name(),
                );
                return Err(syn::Error::new(unhandled_panic_span, msg));
            }
            (F::CurrentThread | F::Local, Some((unhandled_panic, _))) => Some(unhandled_panic),
            (_, None) => None,
        };

        Ok(FinalConfig {
            name: self.name.clone(),
            crate_name: self.crate_name.clone(),
            flavor,
            worker_threads,
            start_paused,
            unhandled_panic,
        })
    }
}

View on GitHub (pinned to 625954f365)

Solutions

  1. Switch the flavor to `current_thread`: `#[tokio::main(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]`.
  2. Or remove `unhandled_panic` and handle task panics via `JoinHandle::is_panicked` / supervision instead.

Example fix

// before
#[tokio::main(flavor = "multi_thread", unhandled_panic = "shutdown_runtime")]
async fn main() {}

// after
#[tokio::main(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
async fn main() {}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Writing `#[tokio::main(flavor = "multi_thread", unhandled_panic = "shutdown_runtime")]`.

Common situations: Wanting panic-shutdown semantics but defaulting to the multi-thread flavor; copying a panic-policy from a single-threaded example into a multi-thread entry point.

Related errors


AI-assisted analysis of tokio-rs/tokio@625954f365 (2026-08-11). Data as JSON: /api/errors/fd558329bd410264. Report an issue: GitHub.