{"record":{"id":"55156c0a10c854b4","repo":"thanos-io/thanos","slug":"lookup-ip-addresses-dual-stack-q","errorCode":null,"errorMessage":"lookup IP addresses (dual-stack) %q","messagePattern":"lookup IP addresses \\(dual-stack\\) %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/discovery/dns/resolver.go","lineNumber":155,"sourceCode":"\t\tif port == \"\" {\n\t\t\treturn nil, errors.Errorf(\"missing port in address given for dnsdualstack lookup: %v\", name)\n\t\t}\n\t\tvar ips []net.IPAddr\n\t\tlookupErrs := errutil.MultiError{}\n\n\t\tfor _, network := range []string{\"ip6\", \"ip4\"} {\n\t\t\taddrs, err := s.resolver.LookupIPAddrByNetwork(ctx, network, host)\n\t\t\tif err != nil {\n\t\t\t\tif !s.resolver.IsNotFound(err) {\n\t\t\t\t\tlookupErrs.Add(err)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tips = append(ips, addrs...)\n\t\t}\n\n\t\tif err := lookupErrs.Err(); len(ips) == 0 && err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"lookup IP addresses (dual-stack) %q\", host)\n\t\t}\n\n\t\tfor _, ip := range ips {\n\t\t\tres = append(res, appendScheme(scheme, net.JoinHostPort(ip.String(), port)))\n\t\t}\n\tdefault:\n\t\treturn nil, errors.Errorf(\"invalid lookup scheme %q\", qtype)\n\t}\n\n\tif res == nil && err == nil {\n\t\tlevel.Warn(s.logger).Log(\"msg\", \"IP address lookup yielded no results. No host found or no addresses found\", \"host\", host)\n\t}\n\n\treturn res, nil\n}\n\nfunc appendScheme(scheme, host string) string {\n\tif scheme == \"\" {","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/discovery/dns/resolver.go#L137-L173","documentation":"In the ADualStack branch of Resolve, lookups run on both 'ip6' and 'ip4' networks and each error is collected into an errutil.MultiError. If no IP addresses were obtained at all AND at least one lookup errored, the resolver wraps and returns the combined error. It means dual-stack DNS resolution completely failed (both address families), not partially.","triggerScenarios":"Calling Resolve with an ADualStack address where LookupIPAddrByNetwork fails for both ip6 and ip4 — hostname does not exist (NXDOMAIN), DNS server unreachable, or ctx canceled — and zero addresses were collected.","commonSituations":"DNS outages or broken resolv.conf in Kubernetes pods; typo'd or deleted service hostnames; a host with neither AAAA nor A records; network policies blocking egress to DNS (port 53).","solutions":["Run nslookup/dig for the hostname with both A and AAAA queries to see why resolution fails.","Fix DNS configuration (resolv.conf, CoreDNS, kube-dns) or network rules blocking port 53.","Correct the hostname in the discovery config; check for typos or removed services.","Wrap Resolve in retry with backoff for transient DNS failures."],"exampleFix":"// before\nips, err := resolver.Resolve(ctx, []string{\"dnsdualstack+http://missing-svc:9090\"})\n// after\nips, err := resolver.Resolve(ctx, []string{\"dnsdualstack+http://existing-svc:9090\"})\nif err != nil {\n    var dnsErr *net.DNSError\n    if errors.As(err, &dnsErr) && dnsErr.IsTemporary {\n        err = backoff.Retry(func() error { _, err = resolver.Resolve(ctx, addrs); return err }, b)\n    }\n}","handlingStrategy":"retry","validationCode":"func canResolveDualStack(host string) error {\n    for _, netw := range []string{\"ip4\", \"ip6\"} {\n        if _, err := net.DefaultResolver.LookupIPAddr(context.Background(), netw, host); err != nil {\n            return fmt.Errorf(\"%s lookup for %q failed: %w\", netw, host, err)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"ips, err := resolver.Resolve(ctx, addrs)\nif err != nil {\n    var dnsErr *net.DNSError\n    if errors.As(err, &dnsErr) && dnsErr.IsTemporary {\n        return backoff.Retry(func() error { _, err = resolver.Resolve(ctx, addrs); return err }, b)\n    }\n    return err // permanent: bad host or DNS misconfig\n}","preventionTips":["Pre-verify that A and AAAA records exist for discovery hostnames.","Harden cluster DNS (CoreDNS replicas, sane resolv.conf ndots).","Do not block DNS egress (port 53) with NetworkPolicies.","Retry with backoff for transient DNS errors; fail fast on permanent ones."],"tags":["dns","network","dual-stack","resolution"],"backgroundTag":"network-request-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}