_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.
What the validator actually queries
_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.
Why one nameserver falls behind
Checking each nameserver directly
+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+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"
donedig +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_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.
What to do when the answers disagree
The pattern that holds up in production
+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.