{"record":{"id":"093b95ace61f35d6","repo":"jeessy2/ddns-go","slug":"interface-s-has-no-usable-s-address","errorCode":null,"errorMessage":"interface %s has no usable %s address","messagePattern":"interface (.+?) has no usable (.+?) address","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/http_client_util.go","lineNumber":34,"sourceCode":"\t}\n\taddrs, err := iface.Addrs()\n\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 != \"\" {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/util/http_client_util.go#L16-L52","documentation":"This error is thrown by getLocalAddrFromInterfaceByNetwork when the named network interface has at least one global-unicast address, but none of them match the requested address family (tcp4 or tcp6). The library binds the HTTP client's dialer to a specific interface and must pick an IP of the family matching the forced dial network; if the interface only has addresses of the other family (e.g. only IPv6 link-local/global addresses while 'tcp4' was requested), it cannot return a usable bind address and fails. Callers (CreateBoundNoProxyHTTPClient) log the failure and fall back to the default interface.","triggerScenarios":"Calling CreateBoundNoProxyHTTPClient(\"tcp4\", ifaceName) on an interface whose addresses are all IPv6, or CreateBoundNoProxyHTTPClient(\"tcp6\", ifaceName) on an interface with only IPv4 addresses. The interface must exist and have a global-unicast address, but not of the requested family.","commonSituations":"Configuring an IPv4-only box/interface for an IPv6-forced client or vice versa; dual-stack servers reached via a tunnel interface that only has one family; containers/veth pairs provisioned with only one address family; typos forcing 'tcp6' in config when the chosen NIC is IPv4-only.","solutions":["Check the interface's actual addresses (ip addr show <iface>) and pass the network that matches the addresses present: \"tcp4\" for an IPv4-only NIC, \"tcp6\" for an IPv6-only NIC","Use network \"tcp\" (or empty/default) instead of \"tcp4\"/\"tcp6\" so any global-unicast address on the interface is accepted","Add the missing address family to the interface (e.g. enable IPv6 or assign an IPv4 address) if the forced family is required","Pick a different interface that has an address of the requested family"],"exampleFix":"// before\nclient := util.CreateBoundNoProxyHTTPClient(\"tcp4\", \"eth0\") // eth0 is IPv6-only\n// after\nclient := util.CreateBoundNoProxyHTTPClient(\"tcp\", \"eth0\") // accept any family on eth0","handlingStrategy":"validation","validationCode":"func hasFamilyAddr(ifaceName, network string) bool {\n\tiface, err := net.InterfaceByName(ifaceName)\n\tif err != nil { return false }\n\taddrs, _ := iface.Addrs()\n\tfor _, a := range addrs {\n\t\tif ipnet, ok := a.(*net.IPNet); ok && ipnet.IP.IsGlobalUnicast() {\n\t\t\tif network == \"tcp4\" && ipnet.IP.To4() != nil { return true }\n\t\t\tif network == \"tcp6\" && ipnet.IP.To4() == nil { return true }\n\t\t\tif network != \"tcp4\" && network != \"tcp6\" { return true }\n\t\t}\n\t}\n\treturn false\n}\n// call util.CreateBoundNoProxyHTTPClient only if hasFamilyAddr(iface, network)","typeGuard":null,"tryCatchPattern":"localIP, err := util.GetLocalAddrFromInterface(ifaceName)\nif err != nil {\n\tlog.Printf(\"interface %s lacks %s address, using default: %v\", ifaceName, network, err)\n\tclient = util.CreateNoProxyHTTPClient(network) // fallback\n}","preventionTips":["Inspect interface addresses (ip addr) before configuring a forced tcp4/tcp6 network","Prefer \"tcp\" when you do not specifically need a single address family","Prefer dual-stack interfaces when IPv6-only or IPv4-only operation is required","Wrap client creation with a check of GetLocalAddrFromInterface output before relying on the bound client"],"tags":["network","ipv4","ipv6","interface-binding","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"}