thanos-io/thanos · error
could not resolve : no servers returned a viable answer…
Error message
could not resolve %s: no servers returned a viable answer. Errs %v
What it means
Returned when lookupFromAnyServer exhausted every configured DNS server without a viable answer: each server either errored (collected in errs) or returned a non-success/non-NXDOMAIN rcode such as SERVFAIL. lookupWithSearchPath then fails with this aggregate for the specific name being resolved.
Solutions
- Check the 'Errs' list at the end of the message for the per-server failure reasons
- Run dig +trace <name> to see where in the delegation chain resolution breaks
- Retry after confirming the authoritative zone for the name is healthy
- Switch to a known-good resolver (e.g. fix resolv.conf nameserver entries)
Defensive patterns
Strategy: retry
Validate before calling
// verify the name resolves via a reference resolver first
if err := probeDNS("8.8.8.8", name); err != nil { /* name itself is broken upstream */ } Try / catch
addrs, err := r.LookupIPAddr(ctx, name)
if err != nil && strings.Contains(err.Error(), "no servers returned a viable answer") {
// SERVFAIL-style transient: back off and retry
time.Sleep(backoff); addrs, err = r.LookupIPAddr(ctx, name)
} Prevention
- Monitor upstream/authoritative DNS health for zones you depend on
- Use multiple independent resolvers in resolv.conf for redundancy
- Check dig +trace when persistent SERVFAILs appear to locate the broken delegation
- Cache last-good discovery results to ride out transient SERVFAILs
When it happens
Trigger: All servers in conf.Servers fail to answer or return rcodes other than RcodeSuccess/RcodeNameError for the requested name and qtype (A/AAAA/SRV).
Common situations: Upstream DNS SERVFAIL due to broken zone delegation; recursive resolver unable to reach authoritative servers; rate limiting or response filtering by corporate DNS; DNSSEC validation failures.
Related errors
- no such host
- could not load resolv.conf
- could not resolve : all servers responded with errors to at…
- resolution against server
- exchange
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/a4c19758d39844a2.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/discovery/dns/miekgdns/lookup.go:114
client := &dns.Client{}
var errs []error
// TODO(bwplotka): Worth to do fanout and grab fastest as golang native lib?
for _, server := range conf.Servers {
servAddr := net.JoinHostPort(server, conf.Port)
msg, err := askServerForName(name, qtype, client, servAddr, true)
if err != nil {
errs = append(errs, errors.Wrapf(err, "resolution against server %s for %s", server, name))
continue
}
if msg.Rcode == dns.RcodeSuccess || msg.Rcode == dns.RcodeNameError {
return msg, nil
}
}
return nil, errors.Errorf("could not resolve %s: no servers returned a viable answer. Errs %v", name, fmtErrs(errs))
}
func fmtErrs(errs []error) string {
b := bytes.Buffer{}
for _, err := range errs {
b.WriteString(";")
b.WriteString(err.Error())
}
return b.String()
}
// askServerForName makes a request to a specific DNS server for a specific
// name (and qtype). Retries with TCP in the event of response truncation,
// but otherwise just sends back whatever the server gave, whether that be a
// valid-looking response, or an error.
func askServerForName(name string, qType dns.Type, client *dns.Client, servAddr string, edns bool) (*dns.Msg, error) {
msg := &dns.Msg{}
View on GitHub (pinned to 35b8b99117)