shadowsocks/shadowsocks-rust · error

tcp-redir

Error message

tcp-redir

What it means

Under the local-redir feature, the TCP_REDIR value is parsed into a RedirType (e.g. redirect, tproxy, not-supported per platform); an unknown name makes .expect("tcp-redir") panic. Parsing is guarded so it only runs when the platform supports a TCP redirect mode at all.

Source

Thrown at src/service/local.rs:761

            if let Some(udp_bind_addr) = matches.get_one::<ServerAddr>("UDP_BIND_ADDR").cloned() {
                local_config.udp_addr = Some(udp_bind_addr);
            }

            if let Some(udp_associate_addr) = matches.get_one::<ServerAddr>("UDP_ASSOCIATE_ADDR").cloned() {
                local_config.udp_associate_addr = Some(udp_associate_addr);
            }

            #[cfg(feature = "local-tunnel")]
            if let Some(addr) = matches.get_one::<Address>("FORWARD_ADDR").cloned() {
                local_config.forward_addr = Some(addr);
            }

            #[cfg(feature = "local-redir")]
            {
                if RedirType::tcp_default() != RedirType::NotSupported
                    && let Some(tcp_redir) = matches.get_one::<String>("TCP_REDIR")
                {
                    local_config.tcp_redir = tcp_redir.parse::<RedirType>().expect("tcp-redir");
                }

                if RedirType::udp_default() != RedirType::NotSupported
                    && let Some(udp_redir) = matches.get_one::<String>("UDP_REDIR")
                {
                    local_config.udp_redir = udp_redir.parse::<RedirType>().expect("udp-redir");
                }
            }

            #[cfg(feature = "local-dns")]
            {
                use shadowsocks_service::local::dns::NameServerAddr;

                use self::local_value_parser::RemoteDnsAddress;

                if let Some(addr) = matches.get_one::<NameServerAddr>("LOCAL_DNS_ADDR").cloned() {
                    local_config.local_dns_addr = Some(addr);
                }

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Use a valid RedirType for your platform: typically "redirect" or "tproxy" on Linux; check RedirType docs for the compiled feature set.
  2. Verify the local-redir feature and OS support before using the flag; omit --tcp-redir if redirect is unsupported.
  3. Log RedirType::tcp_default() in a debug build to see the accepted default for the platform.

Example fix

// before
sslocal --tcp-redir tproxy ...   # on a platform without tproxy

// after
sslocal --tcp-redir redirect ...   # or omit --tcp-redir
Defensive patterns

Strategy: validation

Validate before calling

if let Some(s) = matches.get_one::<String>("TCP_REDIR") {
    if s.parse::<shadowsocks::local::net::RedirType>().is_err() {
        return Err(format!("invalid tcp-redir for this platform: {}", s));
    }
}

Try / catch

let t = s.parse::<RedirType>().unwrap_or_else(|_| {
    eprintln!("invalid tcp-redir: {}", s);
    std::process::exit(2);
});

Prevention

When it happens

Trigger: Running sslocal with --tcp-redir set to a value RedirType::from_str doesn't recognize on this platform — e.g. "tproxy" on a build/platform where only "redirect" is valid, or misspelled names like "tpproxy".

Common situations: Copying Linux tproxy examples onto a macOS/BSD build; feature flags compiled out; case/typo errors; using names from other proxy tools (e.g. "nftables").

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/8f32e9ba77177ba0. Report an issue: GitHub.