shadowsocks/shadowsocks-rust · error
server-addr
Error message
server-addr
What it means
The `SERVER_ADDR` CLI value is parsed with `svr_addr.parse::<ServerAddr>().expect("server-addr")`. The panic means the string is not a valid SIP002 server address — it must be a `host:port` (or `hostname:port`) pair. Invalid hosts, missing port, or malformed IPv6 literals all fail this parse.
Source
Thrown at src/service/server.rs:355
.expect("`method` is required");
let password = match matches.get_one::<String>("PASSWORD") {
Some(pwd) => read_variable_field_value(pwd).into(),
None => {
// NOTE: svr_addr should have been checked by crate::vparser
if method.is_none() {
// If method doesn't need a key (none, plain), then we can leave it empty
String::new()
} else {
match crate::password::read_server_password(svr_addr) {
Ok(pwd) => pwd,
Err(..) => panic!("`password` is required for server {svr_addr}"),
}
}
}
};
let svr_addr = svr_addr.parse::<ServerAddr>().expect("server-addr");
let timeout = matches.get_one::<u64>("TIMEOUT").map(|x| Duration::from_secs(*x));
let mut sc = match ServerConfig::new(svr_addr, password, method) {
Ok(sc) => sc,
Err(err) => {
panic!("failed to create ServerConfig, error: {}", err);
}
};
if let Some(timeout) = timeout {
sc.set_timeout(timeout);
}
if let Some(p) = matches.get_one::<String>("PLUGIN").cloned() {
let plugin = PluginConfig {
plugin: p,
plugin_opts: matches.get_one::<String>("PLUGIN_OPT").cloned(),
plugin_args: Vec::new(),
plugin_mode: matchesView on GitHub (pinned to 8eb0f0a65b)
Solutions
- Supply a valid `host:port` pair, e.g. `-s "0.0.0.0:8388"`
- Bracket IPv6 literals: `-s "[::]:8388"`
- Strip any scheme prefix and trim whitespace from the value
- Use a config file with a properly validated `server` field for complex setups
Example fix
// before ssserver -s "0.0.0.0" -p "pass" -m aes-256-gcm // after ssserver -s "0.0.0.0:8388" -p "pass" -m aes-256-gcm
Defensive patterns
Strategy: validation
Validate before calling
use std::net::ToSocketAddrs;
fn valid_server_addr(s: &str) -> bool {
s.rsplit_once(':').map(|(h, p)| p.parse::<u16>().is_ok() && !h.is_empty()).unwrap_or(false)
&& s.to_socket_addrs().is_ok()
} Type guard
fn looks_like_host_port(s: &str) -> bool {
s.rsplit_once(':').map(|(h, p)| !h.is_empty() && p.parse::<u16>().is_ok()).unwrap_or(false)
} Try / catch
// parse explicitly with guidance
let addr: ServerAddr = s.parse().map_err(|_| anyhow!("-s must be host:port (IPv6 needs brackets: [::1]:8388)"))?; Prevention
- Always include a port with -s
- Bracket IPv6 literals: [2001:db8::1]:8388
- Trim whitespace and never include scheme prefixes
When it happens
Trigger: Running `ssserver`/managers with `-s` values like `0.0.0.0` (no port), `:8388` (no host), `example.com` (no port), or unbracketed IPv6 like `-s ::1:8388`.
Common situations: Forgetting the port; writing IPv6 addresses without brackets (`[::1]:8388` is required); trailing whitespace or protocol prefixes (`udp://host:port`).
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- method
- method
- not supported `protocol` "{p}"
- invalid `dns` value, can only be [(tcp|udp)://]host[:port][,
- plugin-mode must be one of `tcp_only` (default), `udp_only`
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/1f1d640bbdb1458f.
Report an issue: GitHub.