shadowsocks/shadowsocks-rust · error

TCP mode have to be enabled for http

Error message

TCP mode have to be enabled for http

What it means

During Config::validate() for a local HTTP-protocol server, the mode must include TCP. If mode.enable_tcp() is false (e.g. mode is udp_only), the config is rejected with ErrorKind::Invalid. HTTP proxying is inherently TCP-based, so an HTTP local cannot operate in a TCP-less mode.

Source

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

                        ErrorKind::MissingField,
                        "missing `local_dns_addr` or `remote_dns_addr` in configuration",
                        None,
                    );
                    return Err(err);
                }
            }
            #[cfg(feature = "local-tunnel")]
            ProtocolType::Tunnel => {
                if self.forward_addr.is_none() {
                    let err = Error::new(ErrorKind::MissingField, "missing `forward_addr` in configuration", None);
                    return Err(err);
                }
            }

            #[cfg(feature = "local-http")]
            ProtocolType::Http => {
                if !self.mode.enable_tcp() {
                    let err = Error::new(ErrorKind::Invalid, "TCP mode have to be enabled for http", None);
                    return Err(err);
                }
            }

            _ => {}
        }

        Ok(())
    }

    // Check if it is a basic format of local
    pub fn is_basic(&self) -> bool {
        if self.protocol != ProtocolType::Socks || self.udp_addr.is_some() {
            return false;
        }

        #[cfg(feature = "local-tunnel")]
        if self.forward_addr.is_some() {

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Set mode to "tcp_only" or "tcp_and_udp" in the configuration.
  2. In code, use Mode::TcpOnly or Mode::TcpAndUdp before validating.
  3. If only UDP relay is needed, use a different local protocol (e.g. tunnel) instead of http.

Example fix

// before
{ "protocol": "http", "mode": "udp_only" }
// after
{ "protocol": "http", "mode": "tcp_and_udp" }
Defensive patterns

Strategy: validation

Validate before calling

if cfg.protocol == ProtocolType::Http && !cfg.mode.enable_tcp() {
    return Err("http protocol requires a TCP-enabled mode (tcp_only or tcp_and_udp)");
}

Type guard

fn mode_ok_for_http(cfg: &Config) -> bool {
    cfg.protocol != ProtocolType::Http || cfg.mode.enable_tcp()
}

Try / catch

match Config::load(path) {
    Ok(cfg) => start(cfg),
    Err(e) if e.to_string().contains("TCP mode have to be enabled") => eprintln!("use tcp_only or tcp_and_udp for http protocol"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling Config::validate() when config_type is Local, protocol is ProtocolType::Http, and the configured Mode (e.g. Mode::UdpOnly parsed from "udp_only") does not enable TCP.

Common situations: Setting "mode": "udp_only" in a config whose "protocol" is "http"; combining a UDP-only global mode with an HTTP local; accidentally flipping mode after protocol was chosen.

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/6b2a4e2fd3cd9442. Report an issue: GitHub.