dbt-labs/dbt-core · 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 `#[{macro_name}(flavor = "current_thread")]` What it means
This compile-time error is produced by the same `FinalConfig::build` step in crates/dbt-runtime-macros/src/entry.rs when the `unhandled_panic` option is set while the resolved runtime flavor is `Threaded` (multi_thread). The `unhandled_panic` knob (e.g. `unhandled_panic = "abort_runtime"`) is only implemented for the current_thread/Local runtime flavors in tokio, so the macro rejects the combination with a syn::Error anchored at the `unhandled_panic` argument's span.
Source
Thrown at crates/dbt-runtime-macros/src/entry.rs:249
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,
})
}
}
fn parse_int(int: syn::Lit, span: Span, field: &str) -> Result<usize, syn::Error> {
match int {View on GitHub (pinned to 0267ce9170)
Solutions
- Switch the flavor to `current_thread`: `#[dbt_runtime::main(flavor = "current_thread", unhandled_panic = "abort_runtime")]`.
- Remove the `unhandled_panic` option if the multi_thread runtime is required.
- If panic propagation is the goal on multi_thread, install a panic hook or join spawned tasks explicitly to detect panics instead of using unhandled_panic.
Example fix
// before
#[dbt_runtime::main(flavor = "multi_thread", unhandled_panic = "abort_runtime")]
async fn main() { /* ... */ }
// after
#[dbt_runtime::main(flavor = "current_thread", unhandled_panic = "abort_runtime")]
async fn main() { /* ... */ } Defensive patterns
Strategy: validation
Validate before calling
// unhandled_panic is only supported on current_thread/local flavors.
const FLAVOR: &str = "multi_thread";
const UNHANDLED_PANIC: Option<&str> = Some("abort_runtime");
const _: () = assert!(UNHANDLED_PANIC.is_none() || FLAVOR != "multi_thread", "unhandled_panic requires flavor = \"current_thread\""); Type guard
fn is_unhandled_panic_compatible(flavor: &str) -> bool {
matches!(flavor, "current_thread" | "local")
} Prevention
- Audit attribute options whenever you switch a macro between flavor = "current_thread" and "multi_thread".
- Use panic hooks or explicit task joining for panic detection on multi_thread runtimes instead of unhandled_panic.
- Keep unhandled_panic = "abort_runtime" only in tests that use the single-threaded flavor.
When it happens
Trigger: Writing `#[dbt_runtime::main(flavor = "multi_thread", unhandled_panic = "abort_runtime")]` (or the equivalent `#[dbt_runtime::test(...)]`), or omitting the flavor (default multi_thread) while passing `unhandled_panic`. Raised in `build` when flavor == RuntimeFlavor::Threaded and self.unhandled_panic is Some.
Common situations: Adding `unhandled_panic = "abort_runtime"` to harden a multi-threaded service entry point; copying tokio attribute configuration between runtimes; tests migrated from single-thread tokio tests to multi_thread without auditing options.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- The `start_paused` option requires the `current_thread` runt
- No such runtime flavor `{s}`. The runtime flavors are `curre
- No such unhandled panic behavior `{s}`. The unhandled panic
- The default runtime flavor is `multi_thread`, but the `rt-mu
- The runtime flavor `multi_thread` requires the `rt-multi-thr
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/aa134af344517d2a.
Report an issue: GitHub.