dbt-labs/dbt-core · critical
failed to initialize default multi-threaded tokio runtime
Error message
failed to initialize default multi-threaded tokio runtime
What it means
`run_cli_with_code` builds the default multi-threaded tokio runtime when multi-thread mode is enabled; `.build()` failure panics with this message. As with the single-worker path, the only realistic cause is the OS failing to create worker threads (thread/pid limits, OOM, oversized stacks).
Solutions
- Raise ulimit -u / container pids limit
- Increase container memory or reduce FS_DEFAULT_MAX_BLOCKING_THREADS / stack size
- Lower parallelism (e.g. --threads) or run on a less constrained machine
- Set RUST_BACKTRACE=1 and report if it persists on a normal machine
Example fix
null
Defensive patterns
Strategy: try-catch
Try / catch
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all().build()
.unwrap_or_else(|e| panic!("runtime init failed: {e}; check ulimit -u and memory")); Prevention
- Raise thread/pid limits on high-core machines
- Reduce FS_DEFAULT_MAX_BLOCKING_THREADS in constrained containers
- Leave memory headroom for per-core worker stacks
- Retry after freeing memory if under transient pressure
When it happens
Trigger: `run_cli` → `run_cli_with_code` selects the multi-thread branch and `tokio::runtime::Builder::new_multi_thread().build()` fails because worker threads cannot be spawned (ulimit, cgroup pids, memory exhaustion) or `FS_DEFAULT_MAX_BLOCKING_THREADS`/stack size settings are unusable.
Common situations: High-core-count machines spawning many worker threads in a constrained container; heavy parallel dbt load; low `ulimit -u`; invalid huge FS_DEFAULT_STACK_SIZE.
Related errors
- failed to initialize 'single-worker' tokio runtime
- {e} {:?}
- {e}
- `crate` set multiple times.
- `EnterGuard` values dropped out of order. Guards returned…
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/378c80be725ef513.
Report an issue: GitHub.
Appendix: source
Thrown at crates/dbt-main/src/main_impl.rs:178
.enable_all()
.thread_stack_size(FS_DEFAULT_STACK_SIZE)
.worker_threads(1)
.max_blocking_threads(1)
.on_thread_start(move || on_tokio_thread_start(&dbt_rt_handle))
.on_thread_stop(on_tokio_thread_stop)
.build()
.expect("failed to initialize 'single-worker' tokio runtime")
} else {
let dbt_rt_handle = dbt_rt.handle().clone();
// Multi-threaded runtime: use default (max parallelism)
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.max_blocking_threads(FS_DEFAULT_MAX_BLOCKING_THREADS)
.thread_stack_size(FS_DEFAULT_STACK_SIZE)
.on_thread_start(move || on_tokio_thread_start(&dbt_rt_handle))
.on_thread_stop(on_tokio_thread_stop)
.build()
.expect("failed to initialize default multi-threaded tokio runtime")
};
// If execution panics, exit with a status 2 (but not if RUST_BACKTRACE is
// set to 1, in which case we want to see the backtrace):
if arg.exit_process_on_panic && std::env::var("RUST_BACKTRACE").unwrap_or_default() != "1" {
std::panic::set_hook(Box::new(|info| {
eprintln!("{} {}", RED.apply_to(format!("{PANIC}:")), info);
let _ = io::stdout().flush();
let _ = io::stderr().flush();
std::process::exit(2);
}));
}
let cst = feature_stack.cli.cancellation_token_source.clone();
let fail_fast = feature_stack.cli.fail_fast.clone();
let token = cst.token();
View on GitHub (pinned to 0267ce9170)