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_config

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Set outbound_bind_addr to a plain IPv4 or IPv6 literal, e.g. `0.0.0.0` or `::`
  2. Remove any port or brackets from the value
  3. Resolve hostnames to an IP yourself before placing them in the config
  4. 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

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


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