shadowsocks/shadowsocks-rust · error
invalid outbound_bind_addr
Error message
invalid outbound_bind_addr
What it means
The global config allows an outbound_bind_addr that all outbound sockets bind to. It must be a bare IP address; the loader parses it with IpAddr::from_str and returns ErrorKind::Invalid 'invalid outbound_bind_addr' if parsing fails.
Source
Thrown at crates/shadowsocks-service/src/config.rs:2600
// SO_MARK
#[cfg(any(target_os = "linux", target_os = "android"))]
if let Some(fwmark) = config.outbound_fwmark {
nconfig.outbound_fwmark = Some(fwmark);
}
// SO_USER_COOKIE
#[cfg(target_os = "freebsd")]
if let Some(user_cookie) = config.outbound_user_cookie {
nconfig.outbound_user_cookie = Some(user_cookie);
}
// Outbound bind() address
if let Some(bind_addr) = config.outbound_bind_addr {
match bind_addr.parse::<IpAddr>() {
Ok(b) => nconfig.outbound_bind_addr = Some(b),
Err(..) => {
let err = Error::new(ErrorKind::Invalid, "invalid outbound_bind_addr", None);
return Err(err);
}
}
}
// Bind device / interface
nconfig.outbound_bind_interface = config.outbound_bind_interface;
if let Some(b) = config.outbound_udp_allow_fragmentation {
nconfig.outbound_udp_allow_fragmentation = b;
}
if let Some(b) = config.inbound_udp_allow_fragmentation {
nconfig.inbound_udp_allow_fragmentation = b;
}
if let Some(proxy_config) = config.outbound_proxy {
nconfig.outbound_proxy = proxy_configView on GitHub (pinned to 8eb0f0a65b)
Solutions
- Set outbound_bind_addr to a plain IPv4 or IPv6 literal, e.g. `0.0.0.0` or `::`
- Remove any port or brackets from the value
- Resolve hostnames to an IP yourself before placing them in the config
- Remove the field if you do not need a specific outbound bind address
Example fix
// before "outbound_bind_addr": "192.168.1.10:0" // after "outbound_bind_addr": "192.168.1.10"
Defensive patterns
Strategy: validation
Validate before calling
fn validate_outbound_bind_addr(a: &str) -> Result<(), String> {
a.parse::<std::net::IpAddr>()
.map(|_| ())
.map_err(|_| format!("outbound_bind_addr must be a bare IP, got: {a}"))
} Type guard
fn is_bare_ip(a: &str) -> bool {
a.parse::<std::net::IpAddr>().is_ok()
} Try / catch
match bind_addr_str.filter(|a| is_bare_ip(a)) {
Some(a) => cfg.outbound_bind_addr = Some(a),
None => eprintln!("outbound_bind_addr must be a plain IPv4/IPv6 address"),
} Prevention
- Never put hostnames, ports, or interface names in outbound_bind_addr
- Strip brackets from IPv6 literals and drop any :port suffix
- Validate the field parses as IpAddr before writing the config
- Omit the field unless you specifically need to force a bind address
When it happens
Trigger: Setting `outbound_bind_addr` to a value that fails `parse::<IpAddr>()`: a hostname, a URL, an IP with port (`1.2.3.4:80`), or an interface name like `eth0`.
Common situations: Putting a hostname where only an IP is accepted; including a port; trying to bind by interface name; leftover IPv6 with brackets `[::1]`.
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
- `protocol` invalid
- invalid `mode`
- `server`, `server_port`, `method`, `password` must be provid
- `users[].password` should be base64 encoded
- invalid `tcp_weight`, must be in [0, 1]
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/81866d62255b4dd0.
Report an issue: GitHub.