risingwavelabs/risingwave · critical

Failed to get available parallelism

Error message

Failed to get available parallelism

What it means

At startup, `init_tokio_runtime` in src/utils/runtime derives the tokio worker-thread count from `std::thread::available_parallelism()`. The `.expect("Failed to get available parallelism")` panics when the OS refuses to report CPU parallelism, so the process cannot size its async runtime. The Rust API returns `Err` when the platform/kernel restricts CPU affinity information (e.g. a cgroup/namespace with an empty cpuset).

Solutions

  1. Set the TOKIO_WORKER_THREADS environment variable (e.g. TOKIO_WORKER_THREADS=8) so available_parallelism() is never called.
  2. Fix the container/cgroup config so at least one CPU is usable (cpuset quota, `--cpus`, cpuset.cpus range).
  3. Run on a supported platform / disable restrictive seccomp filters blocking sched_getaffinity.

Example fix

// before: unavailable parallelism panics
let threads = std::thread::available_parallelism().expect("Failed to get available parallelism").get();
// after: guard with env var or fallback
let threads = std::env::var("TOKIO_WORKER_THREADS").ok()
    .and_then(|v| v.parse::<usize>().ok())
    .or_else(|| std::thread::available_parallelism().ok().map(|n| n.get()))
    .unwrap_or(4);
Defensive patterns

Strategy: validation

Validate before calling

let workers = std::env::var("TOKIO_WORKER_THREADS").ok()
    .and_then(|v| v.parse::<usize>().ok())
    .or_else(|| std::thread::available_parallelism().ok().map(|n| n.get()));
if workers.is_none() {
    eprintln!("CPU parallelism unavailable; set TOKIO_WORKER_THREADS explicitly");
}

Prevention

When it happens

Trigger: Process started in release mode (not debug_assertions) without TOKIO_WORKER_THREADS set, and `available_parallelism()` returns Err — typically because the process has no CPUs available in its cgroup cpuset, a restrictive seccomp/LSM policy, or an unsupported/obscure platform target.

Common situations: Containers/Kubernetes pods with cpuset limits that remove all CPUs; sandboxes (CI runners, gVisor, some seccomp profiles) blocking sched_getaffinity; embedded or unusual libc targets where available_parallelism is unsupported.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/7c9487edd06f3ae5. Report an issue: GitHub.

Appendix: source

Thrown at src/utils/runtime/src/lib.rs:97

            tracing::error!(?e, "Failed to install default crypto provider.");
        })
        .unwrap();
    risingwave_variables::init_server_start_time();

    // `TOKIO` will be read by tokio. Duplicate `RW` for compatibility.
    if let Some(worker_threads) = std::env::var_os("RW_WORKER_THREADS") {
        // safety: single-threaded now.
        unsafe { std::env::set_var("TOKIO_WORKER_THREADS", worker_threads) };
    }

    // Set the default number of worker threads to be at least `MIN_WORKER_THREADS`, in production.
    if !cfg!(debug_assertions) {
        let worker_threads = match std::env::var("TOKIO_WORKER_THREADS") {
            Ok(v) => v
                .parse::<usize>()
                .expect("Failed to parse TOKIO_WORKER_THREADS"),
            Err(std::env::VarError::NotPresent) => std::thread::available_parallelism()
                .expect("Failed to get available parallelism")
                .get(),
            Err(_) => panic!("Failed to parse TOKIO_WORKER_THREADS"),
        };
        if worker_threads < MIN_WORKER_THREADS {
            tracing::warn!(
                "the default number of worker threads ({worker_threads}) is too small, which may lead to issues, increasing to {MIN_WORKER_THREADS}"
            );
            // safety: single-threaded now.
            unsafe { std::env::set_var("TOKIO_WORKER_THREADS", MIN_WORKER_THREADS.to_string()) };
        }
    }

    if let Ok(enable_deadlock_detection) = std::env::var("RW_DEADLOCK_DETECTION") {
        let enable_deadlock_detection = enable_deadlock_detection
            .parse()
            .expect("Failed to parse RW_DEADLOCK_DETECTION");
        if enable_deadlock_detection {
            enable_parking_lot_deadlock_detection();

View on GitHub (pinned to 6469eb736d)