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

  1. Use http:// or https:// for the target address handled by HttpClient
  2. Route SOCKS/other-scheme traffic through the appropriate local server (socks/mod.rs), not the HTTP client
  3. Fix the configuration so the scheme field matches the HTTP forwarder's supported values
  4. 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

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


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)