v2rayA/v2rayA · error
no suitable IPv4 address found
Error message
no suitable IPv4 address found
What it means
The IPv4 branch of GetBestLocalIP: when preferIPv6 is false and no suitable IPv4 address was found on any interface, it returns "no suitable IPv4 address found". It complements the IPv6 error and surfaces when the host genuinely lacks a usable IPv4 unicast address for binding.
Source
Thrown at service/kernel/v2ray/template_inbound.go:105
}
}
} else {
if ip.To4() != nil {
// IPv4 address
return ip, nil
}
}
}
}
if bestIP != nil {
return bestIP, nil
}
if preferIPv6 {
return nil, errors.New("no suitable IPv6 address found")
}
return nil, errors.New("no suitable IPv4 address found")
}
// GetLinkLocalIPv6 returns a link-local IPv6 address as fallback
func GetLinkLocalIPv6() (net.IP, error) {
interfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for _, iface := range interfaces {
if iface.Flags&net.FlagUp == 0 {
continue
}
// Skip TUN interfaces
ifName := strings.ToLower(iface.Name)
if strings.Contains(ifName, "tun") || strings.Contains(ifName, "tap") {
continueView on GitHub (pinned to 71e5442fc5)
Solutions
- Switch the preference to IPv6 (preferIPv6=true) if the host is IPv6-only.
- Bring up an interface with an IPv4 address or assign one (ip addr add / DHCP).
- Review the filter logic in GetBestLocalIP to confirm the existing IPv4 address isn't wrongly excluded.
- Provide an explicit sendThrough address in the config instead of auto-selection.
Example fix
// before ip, err := GetBestLocalIP(false) // IPv4-only preference on IPv6-only host // after ip, err := GetBestLocalIP(true) // use IPv6 when no IPv4 is available
Defensive patterns
Strategy: fallback
Validate before calling
hasV4 := false
addrs, _ := net.InterfaceAddrs()
for _, a := range addrs {
if ipn, ok := a.(*net.IPNet); ok && ipn.IP.To4() != nil && ipn.IP.IsGlobalUnicast() {
hasV4 = true
}
}
if !hasV4 { preferIPv6 = true } Type guard
func hostHasIPv4() bool {
addrs, err := net.InterfaceAddrs()
if err != nil { return false }
for _, a := range addrs {
if ipn, ok := a.(*net.IPNet); ok && ipn.IP.To4() != nil && ipn.IP.IsGlobalUnicast() { return true }
}
return false
} Try / catch
ip, err := GetBestLocalIP(false)
if err != nil {
ip, err = GetBestLocalIP(true)
if err != nil { return fmt.Errorf("no usable bind address: %w", err) }
} Prevention
- Ensure at least one interface has an IPv4 address before enabling the service.
- On IPv6-only hosts, prefer IPv6 selection or set sendThrough explicitly.
- Check interface state (not just addresses) when diagnosing.
When it happens
Trigger: Calling GetBestLocalIP with preferIPv6=false on a host with no non-loopback (per filter) IPv4 address — e.g. IPv6-only environment or interfaces down.
Common situations: IPv6-only containers/VPS; all interfaces except loopback down; unusual filtering that excludes the host's IPv4 addresses; misconfigured sendThrough preference on an IPv6-only box.
Related errors
- no suitable IPv6 address found
- failed to create anytls stream
- failed to write destination to anytls stream
- anytls connection ends
- juicity: failed to dial destination
AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05).
Data as JSON: /api/errors/07d9be0ae216b661.
Report an issue: GitHub.