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

  1. Add an explicit port to the address used with the ADualStack scheme (e.g. host:9090).
  2. If ports should come from DNS SRV records, use the SRV scheme instead of ADualStack.
  3. 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

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


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)