shadowsocks/shadowsocks-rust · error

udp-redir

Error message

udp-redir

What it means

Analogous to the tcp case: under the local-redir feature, UDP_REDIR is parsed into RedirType and .expect("udp-redir") panics on an unknown value. It only evaluates when the platform has a UDP-capable redirect default (tproxy on Linux; many platforms have no UDP redirect).

Source

Thrown at src/service/local.rs:767

            }

            #[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);
                }

                if let Some(addr) = matches.get_one::<RemoteDnsAddress>("REMOTE_DNS_ADDR").cloned() {
                    local_config.remote_dns_addr = Some(addr.0);
                }
            }

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Use "tproxy" for --udp-redir on Linux; on platforms without UDP redirect, omit the flag entirely.
  2. Check RedirType::udp_default() != NotSupported for your build before using the flag.
  3. Correct typos so the string matches the RedirType FromStr implementation exactly.

Example fix

// before
sslocal --udp-redir redirect ...

// after
sslocal --udp-redir tproxy ...
Defensive patterns

Strategy: validation

Validate before calling

if let Some(s) = matches.get_one::<String>("UDP_REDIR") {
    match s.parse::<shadowsocks::local::net::RedirType>() {
        Ok(t) if t != shadowsocks::local::net::RedirType::NotSupported => {}
        _ => return Err(format!("udp-redir '{}' unsupported on this platform (use tproxy on Linux)", s)),
    }
}

Try / catch

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

Prevention

When it happens

Trigger: Passing --udp-redir with a name not valid for the platform/build, such as "redirect" (TCP-only mechanism) where only "tproxy" supports UDP, or a typo like "udtproxy".

Common situations: Assuming redirect supports UDP (it does not); enabling --udp-redir on macOS/BSD where UDP redirect is unsupported; typos and case mistakes.

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