nautechsystems/nautilus_trader · critical
Failed to create tokio runtime
Error message
Failed to create tokio runtime
What it means
`initialize_runtime` builds the global tokio runtime via `Builder::enable_all().build()` and panics if tokio fails to construct it. Tokio's `build` fails only in degenerate conditions such as an invalid worker_threads/core configuration or resource/OS-level failure creating the runtime's I/O and timer drivers.
Source
Thrown at crates/common/src/live/runtime.rs:88
{
crate::python::runtime::initialize_python();
}
let worker_threads = std::env::var(NAUTILUS_WORKER_THREADS)
.ok()
.and_then(|val| val.parse::<usize>().ok())
.unwrap_or_default();
let mut builder = Builder::new_multi_thread();
if worker_threads > 0 {
builder.worker_threads(worker_threads);
}
builder
.enable_all()
.build()
.expect("Failed to create tokio runtime")
}
/// Sets a custom pre-built Tokio runtime as the global Nautilus runtime.
///
/// Must be called before the first [`get_runtime`] invocation (i.e. before
/// `LiveNode::build()` or any adapter/client usage). This gives callers who
/// own `main()` full control over worker threads, blocking threads, thread
/// names, stack sizes, and any other [`tokio::runtime::Builder`] options.
///
/// # Runtime Requirements
///
/// The supplied runtime must be multi-threaded and have all Tokio drivers
/// enabled with `tokio::runtime::Builder::enable_all()`.
///
/// # Errors
///
/// Returns `Err(runtime)` if a runtime was already initialized.
pub fn set_runtime(runtime: tokio::runtime::Runtime) -> Result<(), tokio::runtime::Runtime> {View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure `worker_threads` is at least 1 (or omit it to use num_cpus default)
- Check config/env that feeds worker_threads for bad values
- If a runtime must already exist, use `set_runtime` with a pre-built runtime before `get_runtime`
- Verify the target platform supports tokio's enabled drivers (enable_all) and the process isn't resource-starved
Example fix
// before initialize_runtime(0); // after initialize_runtime(4); // >= 1 worker thread
Defensive patterns
Strategy: validation
Validate before calling
let workers = worker_threads.max(1); initialize_runtime(workers);
Type guard
fn valid_worker_threads(n: usize) -> bool { n >= 1 } Try / catch
// Panics cannot be caught in Rust without catch_unwind; validate inputs beforehand std::panic::catch_unwind(|| initialize_runtime(4)).is_err() // last resort only
Prevention
- Never pass 0 for worker_threads
- Prefer the default runtime (omit worker_threads) unless tuning is required
- Use set_runtime with a pre-built runtime when you need custom configuration
- Call initialize_runtime once, early, before any get_runtime usage
When it happens
Trigger: Calling `initialize_runtime` (directly or via `get_runtime` first-use) when tokio cannot build a multi-thread runtime, e.g. worker_threads set to 0 or invalid, or environment/resource constraints preventing driver setup.
Common situations: Passing an invalid `worker_threads` value (0) from config; embedding Nautilus in a process that forbids creating reactor/timer drivers; conflicting prior runtime setup.
Related errors
- Latency model should be initialized
- Execution client should be initialized
- task slot is already occupied
- Failed to start Coinbase WebSocket handler task: {e}
- Failed to start Lighter WebSocket handler task: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bceef6b6d29c2cf8.
Report an issue: GitHub.