DNS response codes — RCODEs — are the small numeric status returned in every DNS reply telling you whether the lookup succeeded and, if not, why. Reading them correctly is the fastest way to tell a missing record apart from a broken resolver or a deliberate policy block. This reference lists the standard codes from the DNS header plus the extended values carried by EDNS and TSIG, each with its RFC and a diagnostic note.
How it works
The original DNS header reserves only 4 bits for the RCODE, so values 0–15 fit inside a normal response. Anything larger is an extended RCODE: the high bits live in the EDNS0 OPT pseudo-record (RFC 6891) or in TSIG/TKEY signature data (RFC 8945). That is why a tool like dig only shows codes such as BADVERS or BADTIME when EDNS or transaction signatures are present.
The most common everyday codes are NOERROR (0), SERVFAIL (2), NXDOMAIN (3) and REFUSED (5). Note that value 16 is overloaded: in an EDNS context it means BADVERS (unsupported OPT version), and in a TSIG context it means BADSIG (signature failure).
Tips and examples
When debugging, map the code to a cause before changing anything:
NXDOMAIN -> the name genuinely does not exist (check for typos / delegation)
SERVFAIL -> resolver problem: upstream down or DNSSEC validation failed
REFUSED -> policy: recursion off, ACL, or zone-transfer denied
NOERROR + 0 answers -> name exists but not for that record type
A frequent DNSSEC pitfall: a validating resolver returns SERVFAIL for a zone with a broken signature, while a non-validating resolver returns the records normally — the difference points straight at a DNSSEC misconfiguration rather than the records themselves.
Detailed diagnostic notes for the most common codes
NOERROR (0) with no answer section. This is not an error but is frequently misread as one. The name exists in DNS but has no record of the type you asked for. For example, an AAAA query for a host that only publishes an A record returns NOERROR with an empty answer. Always check the additional and authority sections for useful hints.
FORMERR (1) — Format Error. The server could not understand your query. This usually means the client is sending a malformed packet, often because it is requesting EDNS extensions at a version or option the server does not understand. If you see this unexpectedly, try stripping EDNS from your query.
SERVFAIL (2). The most ambiguous code in practice. Common causes include:
- The authoritative nameserver for the zone is unreachable or timed out.
- DNSSEC validation failed (the signature is expired, broken, or the DS record in the parent does not match the zone’s DNSKEY).
- A zone delegation loop or missing glue records.
To distinguish a DNSSEC failure from an unreachable server, compare a validating resolver’s response against a non-validating one. If only the validating resolver returns SERVFAIL, the zone’s signatures are the culprit.
NXDOMAIN (3) — Non-Existent Domain. The name does not exist anywhere in the zone or its delegated subtree. This is authoritative — the zone has responded and confirmed the name is absent. Check for typos, verify the delegation chain, and confirm the record was published correctly. Some ISPs hijack NXDOMAIN responses to redirect to search pages; if you suspect this, check with a public resolver.
REFUSED (5). The server understood the query but its policy says no. Recursion is disabled for your IP address, you are attempting a zone transfer without being an authorised secondary, or a local firewall is returning a synthetic REFUSED. It is a deliberate block, not a server failure.
BADTIME (18) — TSIG clock skew. TSIG timestamps must fall within a configurable fudge window (typically 300 seconds). A clock difference larger than that produces BADTIME. Sync both sides to an NTP source and the error disappears.