shadowsocks/shadowsocks-rust · error
HTTP/HTTPS outbound proxy requires the `local-http` feature
Error message
HTTP/HTTPS outbound proxy requires the `local-http` feature
What it means
The outbound proxy chain supports HTTP/HTTPS CONNECT proxies only when the crate is compiled with the `local-http` feature. negotiate_hop explicitly rejects Http/Https hop kinds with io::ErrorKind::Unsupported in builds without that feature. The proxy config parsed fine; the capability was compiled out.
Source
Thrown at crates/shadowsocks-service/src/net/outbound/chain.rs:125
mut stream: OutboundProxyStream,
hop: &OutboundProxyHop,
next_target: &Address,
) -> io::Result<OutboundProxyStream> {
match &hop.kind {
OutboundProxyKind::Socks5 { auth } => {
Socks5Negotiator::establish_tcp(&mut stream, next_target.clone(), auth)
.await
.map_err(io::Error::other)?;
Ok(stream)
}
#[cfg(feature = "local-http")]
OutboundProxyKind::Http { auth } | OutboundProxyKind::Https { auth, .. } => {
let local_addr = stream.local_addr()?;
let tunnel = HttpConnectClient::establish(stream, next_target, auth).await?;
Ok(OutboundProxyStream::from_http(local_addr, tunnel))
}
#[cfg(not(feature = "local-http"))]
OutboundProxyKind::Http { .. } | OutboundProxyKind::Https { .. } => Err(io::Error::new(
io::ErrorKind::Unsupported,
"HTTP/HTTPS outbound proxy requires the `local-http` feature",
)),
}
}
#[cfg(any(feature = "local-http-native-tls", feature = "local-http-rustls"))]
async fn tls_wrap(stream: OutboundProxyStream, sni: &str) -> io::Result<OutboundProxyStream> {
let local_addr = stream.local_addr()?;
let tls = tls_connect(stream, sni).await?;
Ok(OutboundProxyStream::from_tls(local_addr, tls))
}
#[cfg(not(any(feature = "local-http-native-tls", feature = "local-http-rustls")))]
async fn tls_wrap(_stream: OutboundProxyStream, _sni: &str) -> io::Result<OutboundProxyStream> {
super::tls::tls_unsupported()
}
View on GitHub (pinned to 8eb0f0a65b)
Solutions
- Rebuild with the feature: cargo build --features local-http (plus the needed TLS backend)
- Change the outbound proxy to a supported kind such as SOCKS5 for the current build
- Check the package/distro build flags to confirm which features are enabled
Example fix
// before cargo build -p shadowsocks-service // after cargo build -p shadowsocks-service --features local-http
Defensive patterns
Strategy: validation
Validate before calling
#[cfg(not(feature = "local-http"))]
if matches!(hop.kind, OutboundProxyKind::Http{..} | OutboundProxyKind::Https{..}) {
return Err(anyhow!("http(s) hop requires building with --features local-http"));
} Type guard
fn is_http_kind(k: &OutboundProxyKind) -> bool {
matches!(k, OutboundProxyKind::Http{..} | OutboundProxyKind::Https{..})
} Try / catch
match negotiate_result {
Err(e) if e.kind() == io::ErrorKind::Unsupported => eprintln!("rebuild with --features local-http"),
other => other?,
} Prevention
- Check crate features before writing http/https hops into config
- Pin build features in CI so all environments match
- Document required features next to the proxy config sample
When it happens
Trigger: A config lists an `http` or `https` outbound proxy hop while the shadowsocks-service crate was built without `--features local-http`; connect_chain/negotiate_hop reaches that hop and returns Unsupported.
Common situations: Using a default `cargo build`/crates.io install that omits feature flags; feature was renamed or dropped between versions; a distro package built with a minimal feature set.
Related errors
- HTTPS outbound proxy requires either `local-http-native-tls`
- {method} don't know how to generate nonce
- invalid outbound_proxy
- resolve empty
- unexpected response from http://clients3.google.com/generate
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/3a5137063e579cda.
Report an issue: GitHub.