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
- Check the nested cause (e) in the error for the exact parse failure
- Fix the proxy URL syntax in the server's outbound_proxy config field
- Use a supported scheme (socks5, http) for outbound_proxy
- 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
- Always use scheme://host:port form for proxy URLs
- Stick to socks5 or http schemes supported by shadowsocks
- Validate proxy URLs when generating configs programmatically
- Read the nested cause error for the precise parse failure
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
- `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/46d9967323cff438.
Report an issue: GitHub.