shadowsocks/shadowsocks-rust · error
invalid scheme
Error message
invalid scheme
What it means
HttpClient::connect only supports plain HTTP and HTTPS schemes; if called with any other Scheme (e.g. SOCKS or other proxy-style schemes parsed from a URI), it immediately returns an io::Error "invalid scheme" (InvalidInput) before establishing any connection.
Solutions
- Use http:// or https:// for the target address handled by HttpClient
- Route SOCKS/other-scheme traffic through the appropriate local server (socks/mod.rs), not the HTTP client
- Fix the configuration so the scheme field matches the HTTP forwarder's supported values
- Add explicit scheme validation in your own config-loading code before calling connect
Example fix
// before let client = HttpClient::connect(context, &Scheme::SOCKS5, host, domain, balancer).await?; // after let client = HttpClient::connect(context, &Scheme::HTTPS, host, domain, balancer).await?;
Defensive patterns
Strategy: validation
Validate before calling
if scheme != Scheme::HTTP && scheme != Scheme::HTTPS {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "HttpClient only supports http/https schemes"));
} Type guard
fn is_http_scheme(s: &Scheme) -> bool {
matches!(s, Scheme::HTTP | Scheme::HTTPS)
} Try / catch
match HttpClient::connect(ctx, &scheme, host, domain, balancer).await {
Err(e) if e.to_string() == "invalid scheme" => eprintln!("use http/https; route other schemes to the matching local server"),
r => r?,
} Prevention
- Validate URL schemes at config-parse time
- Route non-HTTP schemes (socks5 etc.) to their dedicated local servers
- Restrict accepted schemes in user-supplied URLs with an allowlist
When it happens
Trigger: Calling HttpClient::connect (or through code paths passing a parsed Scheme) with a scheme other than Scheme::HTTP or Scheme::HTTPS — e.g. an outbound URL like socks5://... fed into the HTTP client.
Common situations: Misconfigured local/http forward target or upstream URL using a non-HTTP scheme; config parser accepting a broader scheme set than the HTTP client supports; user puts a proxy:// URL where an http(s):// URL is expected.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- balancer.check_interval must be > 0
- balancer.max_server_rtt must be > 0
- empty outbound proxy chain
- failed to create ServerConfig, error
- invalid dnsname
AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09).
Data as JSON: /api/errors/50252ba7a584cc7c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/shadowsocks-service/src/local/http/http_client.rs:321
Http1(http1::SendRequest<B>),
Http2(http2::SendRequest<B>),
}
impl<B> HttpConnection<B>
where
B: Body + Send + Unpin + 'static,
B::Data: Send,
B::Error: Into<Box<dyn ::std::error::Error + Send + Sync>>,
{
async fn connect(
context: Arc<ServiceContext>,
scheme: &Scheme,
host: Address,
domain: &str,
balancer: Option<&PingBalancer>,
) -> io::Result<Self> {
if *scheme != Scheme::HTTP && *scheme != Scheme::HTTPS {
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid scheme"));
}
let (stream, _) = connect_host(context, &host, balancer).await?;
if *scheme == Scheme::HTTP {
Self::connect_http_http1(scheme, host, stream).await
} else if *scheme == Scheme::HTTPS {
Self::connect_https(scheme, host, domain, stream).await
} else {
unreachable!()
}
}
async fn connect_http_http1(scheme: &Scheme, host: Address, stream: AutoProxyClientStream) -> io::Result<Self> {
trace!(
"HTTP making new HTTP/1.1 connection to host: {}, scheme: {}",
host, scheme
);View on GitHub (pinned to 8eb0f0a65b)