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

  1. Ensure `worker_threads` is at least 1 (or omit it to use num_cpus default)
  2. Check config/env that feeds worker_threads for bad values
  3. If a runtime must already exist, use `set_runtime` with a pre-built runtime before `get_runtime`
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/bceef6b6d29c2cf8. Report an issue: GitHub.