thanos-io/thanos · error
lookup IP addresses (dual-stack)
Error message
lookup IP addresses (dual-stack) %q
What it means
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.
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.
Example fix
// before
ips, err := resolver.Resolve(ctx, []string{"dnsdualstack+http://missing-svc:9090"})
// after
ips, err := resolver.Resolve(ctx, []string{"dnsdualstack+http://existing-svc:9090"})
if err != nil {
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) && dnsErr.IsTemporary {
err = backoff.Retry(func() error { _, err = resolver.Resolve(ctx, addrs); return err }, b)
}
} Defensive patterns
Strategy: retry
Validate before calling
func canResolveDualStack(host string) error {
for _, netw := range []string{"ip4", "ip6"} {
if _, err := net.DefaultResolver.LookupIPAddr(context.Background(), netw, host); err != nil {
return fmt.Errorf("%s lookup for %q failed: %w", netw, host, err)
}
}
return nil
} Try / catch
ips, err := resolver.Resolve(ctx, addrs)
if err != nil {
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) && dnsErr.IsTemporary {
return backoff.Retry(func() error { _, err = resolver.Resolve(ctx, addrs); return err }, b)
}
return err // permanent: bad host or DNS misconfig
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- no such host
- could not resolve : all servers responded with errors to at…
- resolution against server
- exchange
- unsupported network
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/55156c0a10c854b4.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/discovery/dns/resolver.go:155
if port == "" {
return nil, errors.Errorf("missing port in address given for dnsdualstack lookup: %v", name)
}
var ips []net.IPAddr
lookupErrs := errutil.MultiError{}
for _, network := range []string{"ip6", "ip4"} {
addrs, err := s.resolver.LookupIPAddrByNetwork(ctx, network, host)
if err != nil {
if !s.resolver.IsNotFound(err) {
lookupErrs.Add(err)
}
continue
}
ips = append(ips, addrs...)
}
if err := lookupErrs.Err(); len(ips) == 0 && err != nil {
return nil, errors.Wrapf(err, "lookup IP addresses (dual-stack) %q", host)
}
for _, ip := range ips {
res = append(res, appendScheme(scheme, net.JoinHostPort(ip.String(), port)))
}
default:
return nil, errors.Errorf("invalid lookup scheme %q", qtype)
}
if res == nil && err == nil {
level.Warn(s.logger).Log("msg", "IP address lookup yielded no results. No host found or no addresses found", "host", host)
}
return res, nil
}
func appendScheme(scheme, host string) string {
if scheme == "" {View on GitHub (pinned to 35b8b99117)