Bali, Indonesia
Insights

Adding the _acme-challenge TXT Record Doesn't Mean Every Nameserver Serves It

October 26, 2026
0:00
A common assumption with DNS-01 validation goes like this: you add the _acme-challenge TXT record in the DNS panel, the panel says it saved, dig from your laptop shows the new value, so the certificate authority must see it too. Then the renewal fails anyway with an error saying the TXT record was not found or did not match. The record is real. The problem is that it is not yet real everywhere the validator might look. A DNS zone is not one server. It is usually two or more authoritative nameservers that are supposed to hold identical copies, and the validator is free to ask any of them. If one copy is behind, a share of validation attempts will hit the stale copy, and that is enough to fail the order.
DNS-01 works by proving you control the zone. The ACME client gets a token from the CA, publishes a value derived from it as a TXT record at _acme-challenge.yourdomain, and tells the CA it is ready. The CA then resolves that name and compares the answer to what it expects. The CA does not ask your DNS panel and it does not ask your laptop's resolver. It resolves the name through its own resolvers, which follow the delegation from the TLD down to whichever nameservers are listed for your domain, and pick one of them. Large CAs also validate from several network locations, so a single order can result in queries landing on different authoritative servers. If ns1 has the new value and ns2 still has the old one, some of those lookups come back wrong. This is also why testing with a plain dig TXT _acme-challenge.example.com proves very little. Your local resolver asked one nameserver, got one answer, and may now be caching it. It tells you nothing about the other servers.
There are a handful of usual reasons, and most of them are boring. The most common is ordinary sync delay. In a classic primary/secondary setup, the panel writes to the primary, and the secondaries pick up the change through a zone transfer. That normally happens when the primary sends a NOTIFY and the secondary sees a higher SOA serial number. If the serial was not bumped, or NOTIFY is blocked by a firewall, the secondary waits until its SOA refresh timer expires, which can be much longer than your ACME client is willing to wait. Managed DNS services with many anycast locations have their own internal propagation, which is usually fast but not instant. The second is a delegation mismatch. The registrar lists the nameservers for the domain in the parent zone (the TLD). If the domain was moved between DNS providers and one old nameserver is still listed at the registrar, that server keeps answering with the zone as it was before the move, or answers nothing useful at all. You edit the record at the new provider, and the old one never hears about it. This is a frequent source of confusion after migrations, because the website works fine: A records rarely change, so the stale server returns the same IP as the current one. The third is a leftover value. ACME clients that fail halfway sometimes leave old TXT records behind, and wildcard plus base-domain certificates legitimately put two values on the same name. Multiple TXT values are allowed, and validators typically accept the order if any value matches. The issue is when one server has only the old value, not when there are several. The last one is caching of an earlier answer. If validation was attempted before the record existed, a resolver along the way may have cached a negative answer (no such record) for the negative TTL defined in your SOA. Retrying immediately can hit that cached negative answer even though every nameserver is now correct.
The fix for all of this is the same habit: stop asking a resolver and ask every authoritative server yourself. Start with what the parent zone says, because that is what the CA follows. +trace walks the delegation from the root, so the second-to-last block of output shows the NS set the TLD hands out.
BASH
# Show the delegation as the TLD publishes it (read-only)
dig +trace NS example.com

# Compare with the NS set the zone itself claims
dig +short NS example.com
If those two lists differ, you have found a delegation problem before even looking at TXT records. The registrar's list is the one that matters for validation, so either update it or make sure every server on it serves the current zone. Next, query each nameserver with recursion turned off. +norec asks the server to answer only from its own data, which is exactly what you want to test.
BASH
# Ask every authoritative server for the challenge record and the SOA serial
domain='example.com'
for ns in (dig +short NS "domain"); do
  echo "== $ns"
  dig +norec +noall +answer TXT "_acme-challenge.domain" @"ns"
  dig +norec +short SOA "domain" @"ns"
done
If the parent delegation lists servers that are missing from dig +short NS, run the same two queries against those names by hand.
TEXT
Illustrative output format:
== ns1.example-dns.net.
_acme-challenge.example.com. 300 IN TXT "new-token-value"
ns1.example-dns.net. hostmaster.example.com. 2026102601 3600 600 1209600 300
== ns2.example-dns.net.
_acme-challenge.example.com. 300 IN TXT "old-token-value"
ns1.example-dns.net. hostmaster.example.com. 2026102501 3600 600 1209600 300
Three things to read from this. First, the TXT value: every server must return the token your client is currently presenting, not one from a previous attempt. Second, the SOA serial (the third field of the SOA line): if one server has a lower serial, it has not received the latest zone, and the problem is synchronization, not your record. Third, the TTL on the TXT answer. A short TTL on _acme-challenge keeps resolvers from holding on to old tokens between renewals. The last SOA field is the negative caching TTL, which controls how long a resolver remembers that a record did not exist. If a nameserver has both IPv4 and IPv6 addresses, it is worth running the check with dig -4 and dig -6 as well. Some setups serve different data, or nothing at all, over one address family, and the validator may use either.
If the serial is behind on one server, give the transfer a chance to happen, then check again. If it never catches up, look at why: the serial may not be incrementing on edits, NOTIFY may not reach the secondary, or the secondary may be refusing the transfer. Where that gets fixed depends on who runs the secondary. On your own BIND or PowerDNS servers you can inspect the logs; on a managed service, the panel or the provider's support is the only place to check. If a server returns the old zone because it is left over from a previous provider, remove it from the registrar's nameserver list. Keeping it there to be safe only guarantees that some fraction of lookups will be answered from data nobody maintains anymore. If every server agrees but validation still failed just a moment ago, wait out the negative TTL before retrying rather than hammering the CA. Repeated failed attempts also count against rate limits, so blind retries make things worse, not better. And if everything matches, serials agree, and the failure message is about something other than the TXT value, look elsewhere. A CAA record that does not authorize your CA produces a failure that looks similar at first glance; Why a CAA Record Can Block Let's Encrypt Renewal and How to Check It covers that check.
For manual renewals, the order is simple: publish the record, query every authoritative nameserver directly until all of them return the new value, and only then tell the CA to validate. The loop above is enough for that. For automated renewals, the same idea should be built into the process. Most ACME clients and their DNS plugins have a setting to wait for propagation before requesting validation, and some can poll the authoritative servers instead of sleeping a fixed time. Polling is the better option where it exists, because a fixed delay is either too long on a good day or too short on a bad one. The exact setting name differs per client, so check its documentation rather than guessing. From the support side, the useful shift is in the first question asked. When a customer says they added the TXT record and it still fails, the question is not whether the record exists, but whether every nameserver in the delegation returns it. That single check, done with +norec against each server, usually separates a sync or delegation problem from a client problem within a few minutes, and it avoids burning renewal attempts on a zone that is only half updated.