shadowsocks/shadowsocks-rust · error

invalid outbound_proxy

Error message

invalid outbound_proxy

What it means

shadowsocks-service validates each server's optional outbound_proxy when loading a service config. The configured proxy is converted into concrete proxy entries via into_proxies(); if that conversion fails (e.g. an unparsable proxy URL or unsupported scheme), the loader aborts with ErrorKind::Invalid and the message 'invalid outbound_proxy', attaching the underlying cause.

Source

Thrown at crates/shadowsocks-service/src/config.rs:2441

                    server_instance.outbound_bind_addr = Some(outbound_bind_addr);
                }

                if let Some(ref outbound_bind_interface) = svr.outbound_bind_interface {
                    server_instance.outbound_bind_interface = Some(outbound_bind_interface.clone());
                }

                if let Some(outbound_udp_allow_fragmentation) = svr.outbound_udp_allow_fragmentation {
                    server_instance.outbound_udp_allow_fragmentation = Some(outbound_udp_allow_fragmentation);
                }

                if let Some(inbound_udp_allow_fragmentation) = svr.inbound_udp_allow_fragmentation {
                    server_instance.inbound_udp_allow_fragmentation = Some(inbound_udp_allow_fragmentation);
                }

                if let Some(proxy_config) = svr.outbound_proxy {
                    server_instance.outbound_proxy = proxy_config
                        .into_proxies()
                        .map_err(|e| Error::new(ErrorKind::Invalid, "invalid outbound_proxy", Some(e)))?;
                }

                nconfig.server.push(server_instance);
            }
        }

        // Set timeout globally
        if let Some(timeout) = config.timeout {
            let timeout = Duration::from_secs(timeout);
            // Set as a default timeout
            for inst in &mut nconfig.server {
                let svr = &mut inst.config;
                if svr.timeout().is_none() {
                    svr.set_timeout(timeout);
                }
            }
        }

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Check the nested cause (e) in the error for the exact parse failure
  2. Fix the proxy URL syntax in the server's outbound_proxy config field
  3. Use a supported scheme (socks5, http) for outbound_proxy
  4. Remove outbound_proxy from the server config if no outbound proxy is needed

Example fix

// before
"outbound_proxy": "socks5//127.0.0.1:1080"
// after
"outbound_proxy": "socks5://127.0.0.1:1080"
Defensive patterns

Strategy: validation

Validate before calling

fn validate_outbound_proxy(p: &str) -> Result<(), String> {
    let (scheme, rest) = p.split_once("://")
        .ok_or_else(|| "proxy URL missing '://'".to_string())?;
    match scheme {
        "socks5" | "http" => (),
        other => return Err(format!("unsupported proxy scheme: {other}")),
    }
    if rest.is_empty() { return Err("proxy URL has empty host".into()); }
    Ok(())
}

Type guard

fn is_supported_proxy_scheme(p: &str) -> bool {
    matches!(p.split_once("://"), Some(("socks5" | "http", _)))
}

Try / catch

match server_cfg.outbound_proxy {
    Some(p) => match p.into_proxies() {
        Ok(proxies) => instance.outbound_proxy = proxies,
        Err(e) => eprintln!("bad outbound_proxy: {e}"),
    },
    None => {}
}

Prevention

When it happens

Trigger: Parsing a server config (JSON or builder) where svr.outbound_proxy is Some, and into_proxies() fails — typically a malformed proxy URL string or a proxy scheme the library does not support.

Common situations: Typo in a socks5/http proxy URL in the JSON config; using a scheme like https:// or vmess:// that shadowsocks outbound proxy does not support; leaving an empty or truncated proxy string after editing the config by hand.

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/46d9967323cff438. Report an issue: GitHub.