{"record":{"id":"8c5a6337e1b89018","repo":"shadowsocks/shadowsocks-rust","slug":"invalid-ipv6-address-8c5a63","errorCode":null,"errorMessage":"Invalid IPv6 address","messagePattern":"Invalid IPv6 address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/shadowsocks/src/net/sys/unix/others.rs","lineNumber":89,"sourceCode":"    }\n}\n\n/// Disable IP fragmentation\n#[inline]\npub fn set_disable_ip_fragmentation<S: AsRawFd>(_af: AddrFamily, _socket: &S) -> io::Result<()> {\n    Ok(())\n}\n\n/// Create a `UdpSocket` with specific address family\n#[inline]\npub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result<UdpSocket> {\n    let bind_addr = match (af, config.bind_local_addr) {\n        (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(),\n        (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => {\n            // Map IPv6 bind_local_addr to IPv4 if AF is IPv4\n            match addr.ip().to_ipv4_mapped() {\n                Some(addr) => SocketAddr::new(IpAddr::from(addr), 0),\n                None => return Err(io::Error::new(ErrorKind::InvalidInput, \"Invalid IPv6 address\")),\n            }\n        }\n        (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(),\n        (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => {\n            // Map IPv4 bind_local_addr to IPv6 if AF is IPv6\n            let ip_addr: IpAddr = addr.ip().to_ipv6_mapped().into();\n            SocketAddr::new(ip_addr, 0)\n        }\n        (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0),\n        (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),\n    };\n\n    bind_outbound_udp_socket(&bind_addr, config).await\n}\n\n/// Create a `UdpSocket` binded to `bind_addr`\npub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, _config: &ConnectOpts) -> io::Result<UdpSocket> {\n    let af = AddrFamily::from(bind_addr);","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks/src/net/sys/unix/others.rs#L71-L107","documentation":"When creating an outbound UDP socket bound to a specific local address, if the requested address family is IPv4 but bind_local_addr is an IPv6 address, the code only accepts IPv4-mapped IPv6 addresses (::ffff:a.b.c.d) and maps them down to IPv4. Any other IPv6 address (e.g. ::1, 2001:db8::1) cannot be used as an IPv4 bind address, so it throws ErrorKind::InvalidInput with \"Invalid IPv6 address\".","triggerScenarios":"Calling create_outbound_udp_socket with AddrFamily::Ipv4 while config.bind_local_addr is a non-IPv4-mapped IPv6 SocketAddr — e.g. bind_local_addr set to \"::\" or a global IPv6 address while the outbound family resolves to IPv4.","commonSituations":"Config file specifying bind_address = \"::\" (dual-stack intent) while the remote server address resolves to IPv4; OS preferring IPv4 for the outbound socket; copying an IPv6 bind config from an IPv6-only setup.","solutions":["Change bind_local_addr to an IPv4 address (e.g. 0.0.0.0 or the desired local IPv4) when binding IPv4 sockets","If you intend dual-stack, use an IPv4-mapped form like \"::ffff:0.0.0.0\" or set an IPv4 address for IPv4 outbound and IPv6 for IPv6 outbound","Set bind_local_addr only when needed — omit it to let the OS choose the source address","Check your config: the address family of bind_local_addr must match (or be mappable to) the outbound address family"],"exampleFix":"# before (config)\nbind_address = \"::\"\n# after\nbind_address = \"0.0.0.0\"  # or omit for OS default","handlingStrategy":"validation","validationCode":"fn bind_addr_valid_for_af(af: shadowsocks::net::AddrFamily, bind: Option<std::net::SocketAddr>) -> bool {\n    match (af, bind) {\n        (shadowsocks::net::AddrFamily::Ipv4, Some(std::net::SocketAddr::V6(v6))) => v6.ip().to_ipv4_mapped().is_some(),\n        (shadowsocks::net::AddrFamily::Ipv6, Some(std::net::SocketAddr::V4(_))) => true, // mapped down\n        _ => true,\n    }\n}","typeGuard":"fn is_ipv4_mapped(addr: &std::net::SocketAddr) -> bool {\n    matches!(addr, std::net::SocketAddr::V6(v6) if v6.ip().to_ipv4_mapped().is_some())\n}","tryCatchPattern":"match create_outbound_udp_socket(context, af, &opts).await {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains(\"Invalid IPv6\") => {\n        eprintln!(\"bind_local_addr is not IPv4-mappable; retrying without explicit bind\");\n        let mut opts2 = opts.clone(); opts2.bind_local_addr = None;\n        create_outbound_udp_socket(context, af, &opts2).await\n    }\n    r => r,\n}","preventionTips":["Keep bind_local_addr family aligned with the outbound/server address family","Prefer 0.0.0.0 / :: (or omit the bind address) unless you specifically need source-IP binding","Run config validation at startup so the mismatch is caught before traffic","When using \"::\" for dual-stack, remember it is NOT mappable to IPv4 — use an IPv4 bind for IPv4 outbound"],"tags":["ipv6","udp","socket","bind","config"],"backgroundTag":"invalid-config-value","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}