thanos-io/thanos · error
missing port in address given for dnsdualstack lookup
Error message
missing port in address given for dnsdualstack lookup: %v
What it means
The DNS service-discovery resolver (Resolve in pkg/discovery/dns/resolver.go) supports A, SRV, and ADualStack lookup schemes. The ADualStack scheme performs IPv6+IPv4 lookups of a hostname and joins each resolved IP with a port. This error is thrown because the ADualStack scheme requires an explicit port, but the target address contained only a host (empty port after parsing), so the resolver refuses to guess a port.
Solutions
- Add an explicit port to the address used with the ADualStack scheme (e.g. host:9090).
- If ports should come from DNS SRV records, use the SRV scheme instead of ADualStack.
- Check the config template/rendering pipeline so the port variable is not empty at render time.
Example fix
// before
res, err := resolver.Resolve(ctx, []string{"dnsdualstack+http://prometheus.monitoring.svc"})
// after
res, err := resolver.Resolve(ctx, []string{"dnsdualstack+http://prometheus.monitoring.svc:9090"}) Defensive patterns
Strategy: validation
Validate before calling
func validateDualStackAddr(addr string) error {
_, port, err := net.SplitHostPort(addr)
if err != nil || port == "" {
return fmt.Errorf("ADualStack scheme requires explicit host:port, got %q", addr)
}
return nil
} Prevention
- Always include a numeric port in dnsdualstack-scheme addresses.
- Use the SRV scheme instead when ports should come from DNS records.
- Render address templates with a fallback default port.
- Add a unit test asserting every configured address parses via net.SplitHostPort.
When it happens
Trigger: Calling Resolve with an ADualStack-scheme address whose host has no port, e.g. 'dnsdualstack+http://myhost/prefix' instead of 'dnsdualstack+http://myhost:9090/prefix'; also when the port portion is empty or stripped by earlier URL parsing.
Common situations: Misconfigured Prometheus/Thanos dns sd_configs; copying an SRV-style config (where ports come from DNS) and switching the scheme to ADualStack without adding a port; config templates where the port variable renders empty.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- no such host
- invalid lookup scheme
- could not load resolv.conf
- could not resolve : all servers responded with errors to at…
- resolution against server
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/d880f23db4bc23a3.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/discovery/dns/resolver.go:138
continue
}
// Do A lookup for the domain in SRV answer.
resIPs, err := s.resolver.LookupIPAddr(ctx, rec.Target)
if err != nil {
if !s.resolver.IsNotFound(err) {
return nil, errors.Wrapf(err, "lookup IP addresses %q", host)
}
if len(resIPs) == 0 {
level.Error(s.logger).Log("msg", "failed to lookup IP addresses", "srv", host, "a", rec.Target, "err", err)
}
}
for _, resIP := range resIPs {
res = append(res, appendScheme(scheme, net.JoinHostPort(resIP.String(), resPort)))
}
}
case ADualStack:
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)
}View on GitHub (pinned to 35b8b99117)