shadowsocks/shadowsocks-rust · critical

create tokio Runtime

Error message

create tokio Runtime

What it means

Identical to the local-service runtime build: the manager service `create` calls `builder.enable_all().build().expect("create tokio Runtime")`. The panic means tokio's Runtime could not be constructed from the given Builder — invalid worker-thread counts or failure to spawn OS threads. Occurs before the manager starts serving.

Source

Thrown at src/service/manager.rs:504

            })?;
        }

        info!("shadowsocks manager {} build {}", crate::VERSION, crate::BUILD_TIME);

        let mut builder = match service_config.runtime.mode {
            RuntimeMode::SingleThread => Builder::new_current_thread(),
            #[cfg(feature = "multi-threaded")]
            RuntimeMode::MultiThread => {
                let mut builder = Builder::new_multi_thread();
                if let Some(worker_threads) = service_config.runtime.worker_count {
                    builder.worker_threads(worker_threads);
                }

                builder
            }
        };

        let runtime = builder.enable_all().build().expect("create tokio Runtime");

        (config, runtime)
    };

    let main_fut = async move {
        let abort_signal = monitor::create_signal_monitor();
        let server = run_manager(config);

        tokio::pin!(abort_signal);
        tokio::pin!(server);

        match future::select(server, abort_signal).await {
            // Server future resolved without an error. This should never happen.
            Either::Left((Ok(..), ..)) => Err(ShadowsocksError::ServerExitUnexpectedly(
                "server exited unexpectedly".to_owned(),
            )),
            // Server future resolved with error, which are listener errors in most cases
            Either::Left((Err(err), ..)) => Err(ShadowsocksError::ServerAborted(format!("server aborted with {err}"))),

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Correct the `--worker-threads` value (>= 1) or drop the flag for defaults
  2. Raise container/rlimit thread (pids) limits
  3. Let tokio use its default multi-thread runtime configuration
  4. Update shadowsocks-rust/tokio versions if platform-specific build bugs apply

Example fix

// before
ssmanager --worker-threads 0 ...
// after
ssmanager ...  # omit --worker-threads
Defensive patterns

Strategy: validation

Validate before calling

// ensure worker-threads is sane before launch
if let Some(n) = cli.worker_threads {
    assert!(n >= 1, "--worker-threads must be >= 1, got {n}");
}

Type guard

fn valid_worker_count(n: u64) -> bool { (1..=1024).contains(&n) }

Try / catch

// expect-panic is fatal; surface it via a friendly startup wrapper
std::panic::set_hook(Box::new(|i| eprintln!("startup failed: {i}")));

Prevention

When it happens

Trigger: `Builder::build()` returning Err inside manager `create` (called from `main`): `--worker-threads 0`, or thread-spawn IO errors under restrictive cgroup/pid limits.

Common situations: Setting worker threads to 0 in scripts; constrained Docker/Kubernetes pods hitting pids limits; hardened rlimits.

Related errors


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/4197e3ee7c7d4000. Report an issue: GitHub.