shadowsocks/shadowsocks-rust · critical

create local

Error message

create local

What it means

After building the tokio runtime, `create` calls `Server::new(config).await.expect("create local")` to construct the local server instance. The panic means the server could not be created from the supplied configuration — typically invalid listener addresses, failed binding-related setup, or bad config values rejected by `Server::new`. Process exits immediately at startup.

Source

Thrown at src/service/local.rs:1004

            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, service_config, runtime)
    };

    let main_fut = async move {
        let config_path = config.config_path.clone();

        let instance = Server::new(config).await.expect("create local");

        let reload_task = match config_path {
            Some(config_path) => ServerReloader {
                config_path: config_path.clone(),
                balancer: instance.server_balancer().clone(),
            }
            .launch_reload_server_task()
            .boxed(),
            None => future::pending().boxed(),
        };

        let abort_signal = monitor::create_signal_monitor();
        let server = instance.run();

        let reload_task = reload_task.fuse();
        let abort_signal = abort_signal.fuse();
        let server = server.fuse();

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Validate the server config (addresses, ports, method/password) before starting
  2. Check the underlying error logged before the panic — fix the offending config field
  3. Test the config with `sslocal --check-config` if available
  4. Ensure bind addresses are valid IP:port and not already restricted

Example fix

// before
sslocal -b "localhost:notaport" -s ... 
// after
sslocal -b "127.0.0.1:1080" -s ...
Defensive patterns

Strategy: validation

Validate before calling

// validate bind address before starting
let addr: std::net::SocketAddr = args.bind_addr
    .parse().expect("bind-addr must be host:port");
assert!(addr.port() > 0, "port must be > 0");

Type guard

fn is_valid_socket_addr(s: &str) -> bool { s.parse::<std::net::SocketAddr>().is_ok() }

Try / catch

// run the server future and inspect its error instead of panicking
match Server::new(config).await {
    Ok(srv) => srv.serve().await,
    Err(e) => eprintln!("failed to create local server: {e}"),
}

Prevention

When it happens

Trigger: `Server::new(config)` returning Err inside `create`, called from `main`: unparseable or unusable server configuration (bad local address, invalid plugin/balancer config, failed ACL/DNS setup).

Common situations: Malformed `-b`/`--bind-addr` values, invalid server address strings in the local forward config, config-file entries that `Server::new` cannot materialize, plugin paths that don't exist.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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