{"record":{"id":"b02212050a36d5e0","repo":"jeessy2/ddns-go","slug":"interface-s-has-no-usable-global-unicast-address","errorCode":null,"errorMessage":"interface %s has no usable global-unicast address","messagePattern":"interface (.+?) has no usable global-unicast address","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/http_client_util.go","lineNumber":36,"sourceCode":"\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"get interface %s addresses failed: %v\", ifaceName, err)\n\t}\n\n\thasGlobalUnicast := false\n\tfor _, addr := range addrs {\n\t\tipNet, ok := addr.(*net.IPNet)\n\t\tif !ok || !ipNet.IP.IsGlobalUnicast() {\n\t\t\tcontinue\n\t\t}\n\t\thasGlobalUnicast = true\n\t\tif isIPMatchedNetwork(ipNet.IP, network) {\n\t\t\treturn ipNet.IP.String(), nil\n\t\t}\n\t}\n\tif hasGlobalUnicast && (network == \"tcp4\" || network == \"tcp6\") {\n\t\treturn \"\", fmt.Errorf(\"interface %s has no usable %s address\", ifaceName, network)\n\t}\n\treturn \"\", fmt.Errorf(\"interface %s has no usable global-unicast address\", ifaceName)\n}\n\nfunc isIPMatchedNetwork(ip net.IP, network string) bool {\n\tswitch network {\n\tcase \"tcp4\":\n\t\treturn ip.To4() != nil\n\tcase \"tcp6\":\n\t\treturn ip.To16() != nil && ip.To4() == nil\n\tdefault:\n\t\treturn true\n\t}\n}\n\nfunc localTCPAddr(ip net.IP, network, ifaceName string) *net.TCPAddr {\n\taddr := &net.TCPAddr{IP: ip}\n\tif network == \"tcp6\" && ifaceName != \"\" {\n\t\taddr.Zone = ifaceName\n\t}","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/util/http_client_util.go#L18-L54","documentation":"This error is thrown by getLocalAddrFromInterfaceByNetwork when the named interface either does not exist as named, has no global-unicast addresses at all, or has no usable address for the requested family. It is the fallback message after checking all addresses; error 65 is the family-specific variant, this one fires when there was no global-unicast address found (hasGlobalUnicast == false) or the network is not tcp4/tcp6. The library needs a bindable IP to pin the HTTP client to the interface and cannot proceed without one.","triggerScenarios":"Calling CreateBoundNoProxyHTTPClient with a network like \"tcp\" on an interface whose addresses are all loopback/link-local/multicast, or an interface that exists but has no global unicast addresses (e.g. a down interface, a bridge with no assigned IP).","commonSituations":"Binding to docker0/bridge interfaces without assigned IPs; interfaces that are DOWN; VPN/tunnel adapters with only link-local addresses; passing a network value other than tcp4/tcp6 while the interface also lacks addresses; environments where the NIC lost its DHCP lease.","solutions":["Verify the interface exists and has a global-unicast address: ip addr show <iface>; look for a global scope inet/inet6 address","Bring the interface up and wait for DHCP/SLAAC to assign an address before creating the client","Choose a different interface that has a global unicast address","If you need family-specific behavior use \"tcp4\" or \"tcp6\" so the family-specific error path (and matching logic) applies"],"exampleFix":"// before\nclient := util.CreateBoundNoProxyHTTPClient(\"tcp\", \"docker0\") // bridge without global addr\n// after\nclient := util.CreateBoundNoProxyHTTPClient(\"tcp\", \"eth0\") // NIC with a global unicast address","handlingStrategy":"validation","validationCode":"func ifaceHasGlobalAddr(ifaceName string) bool {\n\tiface, err := net.InterfaceByName(ifaceName)\n\tif err != nil { return false }\n\tif iface.Flags&net.FlagUp == 0 { return false }\n\taddrs, err := iface.Addrs()\n\tif err != nil { return false }\n\tfor _, a := range addrs {\n\t\tif ipnet, ok := a.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() { return true }\n\t}\n\treturn false\n}\n// only pass ifaceName to CreateBoundNoProxyHTTPClient if ifaceHasGlobalAddr(ifaceName)","typeGuard":null,"tryCatchPattern":"_, err := util.GetLocalAddrFromInterface(ifaceName)\nif err != nil {\n\tlog.Printf(\"cannot bind to %s: %v; falling back to default routing\", ifaceName, err)\n\tclient = util.CreateNoProxyHTTPClient(network)\n}","preventionTips":["Ensure the target interface is UP and holds a global-scope address before binding","Avoid binding to bridges/tun devices that have no assigned IP","Monitor interface address state (DHCP lease expiry) in long-running services","Log and compare against `ip addr show` output when debugging binding failures"],"tags":["network","interface-binding","ipv6","go"],"backgroundTag":"no-suitable-interface-address","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}