dbt-labs/dbt-core · error · syn::Error
The runtime flavor `multi_thread` requires the `rt-multi-thr
Error message
The runtime flavor `multi_thread` requires the `rt-multi-thread` feature.
What it means
When flavor = "multi_thread" is explicitly requested but the `rt-multi-thread` cargo feature is not compiled in, the runtime Builder type does not exist, so the macro fails compilation with this message at Span::call_site(). This is the branch of the same check as error 478, taken when the user explicitly set the flavor.
Source
Thrown at crates/dbt-runtime-macros/src/entry.rs:227
let worker_threads = match (flavor, self.worker_threads) {
(F::CurrentThread | F::Local, Some((_, worker_threads_span))) => {
let msg = format!(
"The `worker_threads` option requires the `multi_thread` runtime flavor. Use `#[{}(flavor = \"multi_thread\")]`",
self.macro_name(),
);
return Err(syn::Error::new(worker_threads_span, msg));
}
(F::CurrentThread | F::Local, None) => None,
(F::Threaded, worker_threads) if self.rt_multi_thread_available => {
worker_threads.map(|(val, _span)| val)
}
(F::Threaded, _) => {
let msg = if self.flavor.is_none() {
"The default runtime flavor is `multi_thread`, but the `rt-multi-thread` feature is disabled."
} else {
"The runtime flavor `multi_thread` requires the `rt-multi-thread` feature."
};
return Err(syn::Error::new(Span::call_site(), msg));
}
};
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!(View on GitHub (pinned to 0267ce9170)
Solutions
- Add the feature: tokio = { version = "1", features = ["rt-multi_thread", "macros"] } — note the exact name is `rt-multi-thread`
- Verify with cargo tree -e features that rt-multi-thread is enabled for tokio
- Switch to flavor = "current_thread" if a single-threaded runtime suffices
Example fix
// before
#[tokio::main(flavor = "multi_thread")]
async fn main() {}
// Cargo.toml: tokio = { version = "1", default-features = false, features = ["rt", "macros"] }
// after
// Cargo.toml: tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "macros"] }
#[tokio::main(flavor = "multi_thread")]
async fn main() {} Defensive patterns
Strategy: validation
Validate before calling
fn assert_flavor_supported(features: &[&str], flavor: &str) -> Result<(), String> {
if flavor == "multi_thread" && !features.contains(&"rt-multi-thread") {
Err("flavor multi_thread requires tokio feature `rt-multi-thread`".into())
} else { Ok(()) }
} Prevention
- Match every flavor = "multi_thread" usage with the rt-multi-thread feature in Cargo.toml
- Verify with cargo tree -e features that the feature reaches the tokio crate
- Switch to current_thread flavor for tests that don't need worker threads
When it happens
Trigger: #[tokio::main(flavor = "multi_thread")] (or #[tokio::test(flavor = "multi_thread")]) while the tokio crate dependency does not include the `rt-multi-thread` feature.
Common situations: Disabling default features in Cargo.toml; CI builds testing no-default-features; a workspace where feature unification leaves tokio without rt-multi-thread; docs examples copied without feature instructions.
Related errors
- The default runtime flavor is `multi_thread`, but the `rt-mu
- No such runtime flavor `{s}`. The runtime flavors are `curre
- No such unhandled panic behavior `{s}`. The unhandled panic
- The `start_paused` option requires the `current_thread` runt
- The `unhandled_panic` option requires the `current_thread` r
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/4890de550f11ef19.
Report an issue: GitHub.