isitdns? wiki/Troubleshooting/What does SERVFAIL mean?
Troubleshooting

❓ What does SERVFAIL mean?

SERVFAIL
general server error
means
the server tried and failed
the code does not say why
not
"that name does not exist"
(that one is NXDOMAIN)
why
ask for the reason: EDE
run
dig @RESOLVER NAME TYPE
then
same again with +cd
code
RCODE 2 (RFC 1035 4.1.1)

Step 1: read the config#

Read what this box is told to do before asking it anything.

side I am asking

systemd-resolved. Read the DNS Servers line, and DNSSEC on or off (resolvectl(1)).

resolvectl status
Global
         Protocols: +LLMNR -mDNS DNSOverTLS=opportunistic DNSSEC=yes/supported
  resolv.conf mode: foreign
Current DNS Server: 1.1.1.1#cloudflare-dns.com
       DNS Servers: 1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google

Any Unix. Read the nameserver lines, in order.

cat /etc/resolv.conf
nameserver 1.1.1.1
nameserver 8.8.8.8
options timeout:2 attempts:2

macOS. Read the first resolver block: that one is the default (scutil(8)). The addresses, search domain and interface below are documentation values.

scutil --dns
DNS configuration

resolver #1
  search domain[0] : example.net
  nameserver[0] : 2001:db8::1
  nameserver[1] : 192.0.2.1
  if_index : 13 (en0)
  flags    : Request A records, Request AAAA records

Windows. Read the DNS Servers line on the adapter carrying the default route (ipconfig).

ipconfig /all

side I run the resolver

BIND. Read forwarders and dnssec-validation as named loaded them (named-checkconf(8)).

named-checkconf -p /etc/bind/named.conf
	dnssec-validation auto;
	recursion yes;
	allow-query {
		"localhost";
	};
	forward only;
	forwarders {
		1.1.1.1;
		8.8.8.8;
	};
};

Unbound. Read the forward zones in use (unbound-control(8)).

unbound-control list_forwards
. IN forward 1.1.1.1 8.8.8.8

Unbound. Read the anchor it validates against; an empty line means unset (unbound-checkconf(8)).

unbound-checkconf -o auto-trust-anchor-file
/var/lib/unbound/root.key

side I run the zone

A zone I own. The parent's DS has to match a key the zone serves.

side I run the zone

Asks for the DS the parent publishes for this zone.

 dig +https @1.1.1.1 dnssec-failed.org DS
; <<>> DiG 9.20.11-0ubuntu0.2-Ubuntu <<>> +https @1.1.1.1 dnssec-failed.org DS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43557
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;dnssec-failed.org. IN DS
;; ANSWER SECTION:
dnssec-failed.org. 3600 IN DS 42069 13 2 62726F6B656E20636861696E206F662074727573742073656E642068 656C7021
;; Query time: 57 msec
;; SERVER: 1.1.1.1#443(1.1.1.1) (HTTPS)
;; WHEN: Sat Sep 19 23:52:38 CDT 2026
;; MSG SIZE rcvd: 94

GO a DS whose key tag and digest match a key the zone publishes

NO GO a key tag no published key has, which is this one

DO zone owner: Fix the DS at the registrar

what each part of this output means →

side I run the zone

Asks the zone for the keys it publishes, validation off so the answer arrives.

 dig +https @1.1.1.1 +cd dnssec-failed.org DNSKEY
; <<>> DiG 9.20.11-0ubuntu0.2-Ubuntu <<>> +https @1.1.1.1 +cd dnssec-failed.org DNSKEY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 366
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; EDE: 9 (DNSKEY Missing): (no SEP matching the DS found for dnssec-failed.org.)
;; QUESTION SECTION:
;dnssec-failed.org. IN DNSKEY
;; ANSWER SECTION:
dnssec-failed.org. 300 IN DNSKEY 256 3 13 +q1YaNu7nKJuMoQ4oAIqg4fvrSwFb/qeEu/2x6KX+r8Rnv0eC448+PnP 9KoI1IETn4W9I7ilBxWsENtLUqxRUg==
dnssec-failed.org. 300 IN DNSKEY 257 3 13 1CcdGV2EigL5bsrPpkSvYHzyfYR1udWKZtWHU9EQXMrbtKglmUDYKKkw wajHQQ7TAMIit/vQbCrh4SPkxLbhgg==
;; Query time: 61 msec
;; SERVER: 1.1.1.1#443(1.1.1.1) (HTTPS)
;; WHEN: Sat Sep 19 23:52:38 CDT 2026
;; MSG SIZE rcvd: 263

GO a 257 key whose tag and digest the DS above carries

NO GO no 257 key matches the DS (EDE 9)

DO zone owner: Fix the signing so a published key matches the DS

what each part of this output means →

Not my resolver and not my zone: go to step 2.

Step 2: dig each layer#

Ask each layer directly, and find the first one that answers differently.

side I am asking

Asks the resolver this client is configured to use, by address, for the name that is failing.

 dig +https @1.1.1.1 dnssec-failed.org A
; <<>> DiG 9.20.11-0ubuntu0.2-Ubuntu <<>> +https @1.1.1.1 dnssec-failed.org A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 49558
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; EDE: 9 (DNSKEY Missing): (no SEP matching the DS found for dnssec-failed.org.)
;; QUESTION SECTION:
;dnssec-failed.org. IN A
;; Query time: 32 msec
;; SERVER: 1.1.1.1#443(1.1.1.1) (HTTPS)
;; WHEN: Sat Sep 19 23:32:30 CDT 2026
;; MSG SIZE rcvd: 103

GO NOERROR and an answer, so this resolver is not where it stops

NO GO SERVFAIL, with an EDE line if the resolver sends one

DO you: Ask a resolver you do not run, below

what each part of this output means →

Swap in the address from step 1. The id, Query time, WHEN and a cached TTL move between runs. +https is DoH and needs dig 9.18 or newer: where port 53 is intercepted, the middle box answers for any @server I name. The interception check.

side I am asking

Asks a resolver you do not run, same name, same type.

 dig +https @8.8.8.8 dnssec-failed.org A
; <<>> DiG 9.20.11-0ubuntu0.2-Ubuntu <<>> +https @8.8.8.8 dnssec-failed.org A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 57170
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; EDE: 9 (DNSKEY Missing): (No DNSKEY matches DS RRs of dnssec-failed.org)
;; QUESTION SECTION:
;dnssec-failed.org. IN A
;; Query time: 112 msec
;; SERVER: 8.8.8.8#443(8.8.8.8) (HTTPS)
;; WHEN: Sat Sep 19 23:16:29 CDT 2026
;; MSG SIZE rcvd: 97

GO an answer here and SERVFAIL above puts it on my resolver or its forwarder

DO you: Open check-a-resolver

NO GO the same SERVFAIL puts it on the zone

DO you: Read the EDE below

what each part of this output means →

check-a-resolver, then check-a-forwarder.

side I run the resolver

Read the EDE the resolver returned:

EDENameReads as
6DNSSEC Bogusvalidation ran and failed
7Signature Expiredan RRSIG has expired
9DNSKEY Missingthe parent's DS matches no published key
10RRSIGs Missingthe signatures are missing
13Cached Errora failure is being served from cache
14Not Readythe server was not fully functional when the query arrived
22No Reachable Authoritynothing answered for the zone
23Network Errorthe resolver's path upstream broke

Causes below, in the order the query travels. RFC 1035 section 4.1.1 gives all of them one code: "Server failure - The name server was unable to process this query due to a problem with the name server".

FamilyWho emits itThe dig that separates itGO and NO GOThe move
nothing authoritative answered (EDE 22, 23)my resolvereach NS, +norecurseGO: one aa. NO GO: all silentzone owner: Check every nameserver in the NS set
the resolver hit a fetch quotamy resolvera second resolver, then mine againGO: mine recovers. NO GO: mine fails under load; fetches-per-zone and fetches-per-server answer SERVFAIL when set to fail (BIND 9 ARM)resolver operator: Check the fetch quotas
a cached failure replayed (EDE 13)my resolverthe same query after the cache windowGO: it answers within the 5 minute ceiling (RFC 9520 section 3.2). NO GO: it still failsyou: Wait out the cache, then ask again
the forwarder failed and nothing falls backmy resolver, forwardingthe forwarder, asked directlyGO: it answers. NO GO: it does not, and forward only (BIND 9 ARM) or forward-first: no (unbound.conf(5)) means no fallbackresolver operator: Fix the forwarder, or drop only
the delegation names servers that do not serve the zone (RFC 9499 section 7)the parent, and the servers it nameseach NS, +norecurseGO: aa from each. NO GO: REFUSED, or NOERROR with no aazone owner: Compare the parent NS set with the child's
the server has the zone and cannot serve it (EDE 14)that authoritative serverthat server, +norecurseGO: aa and the SOA. NO GO: SERVFAIL, or a secondary past its SOA expire, no longer authoritative (RFC 1035 section 3.3.13)zone owner: Check the primary and the last transfer
DNSSEC validation failed (EDE 6, 7, 9, 10)my resolverthe same query with +cdGO: +cd changes nothing. NO GO: +cd answers (RFC 4035 section 5.5)zone owner: Fix the DS, or re-sign the zone

Each row names its own dig. The authoritative server itself: check-an-auth.

Step 3: compare against the path#

Compare where it should have gone with what answered.

you -> stub resolver -> your resolver -> forwarder, if the config named one
                                      -> root -> TLD -> the zone's NS set

The first mismatch is the fault.

The ;; SERVER: line names the socket that answered. +nsid names the anycast instance behind it, for a ticket, where the operator publishes one (RFC 5001).

side I run the zone

Compare what the parent hands out with the NS set the zone serves. check-a-delegation.

side I run the zone

Asks a TLD server which nameservers the parent delegates this zone to.

 dig -4 +norecurse @a0.org.afilias-nst.info dnssec-failed.org NS
; <<>> DiG 9.18.39-0ubuntu0.22.04.6-Ubuntu <<>> -4 +norecurse @a0.org.afilias-nst.info dnssec-failed.org NS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65310
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 5, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;dnssec-failed.org. IN NS
;; AUTHORITY SECTION:
dnssec-failed.org. 3600 IN NS dns101.comcast.net.
dnssec-failed.org. 3600 IN NS dns105.comcast.net.
dnssec-failed.org. 3600 IN NS dns104.comcast.net.
dnssec-failed.org. 3600 IN NS dns102.comcast.net.
dnssec-failed.org. 3600 IN NS dns103.comcast.net.
;; Query time: 131 msec
;; SERVER: 199.19.56.1#53(a0.org.afilias-nst.info) (UDP)
;; WHEN: Sun Sep 20 11:25:38 UTC 2026
;; MSG SIZE rcvd: 162

GO a referral, no aa and no ra, with the NS set in AUTHORITY

NO GO ra set, so a recursive server answered in the TLD server's place

DO you: Run it from a network that leaves port 53 alone

what each part of this output means →

An answer carrying ra came from a recursive server, whatever the ;; SERVER: line says. A +trace on an intercepting network walks someone else's path. Trace from outside it, or in the dig tool.

Then wait. A failure is cached 1 second to 5 minutes (RFC 9520 section 3.2), so a correct fix still answers SERVFAIL for a few minutes.

See also#