Bali, Indonesia
Insights

Pruning Stale _acme-challenge Records to Prevent DNS-01 Validation Errors

October 18, 2026
0:00
When an automated SSL/TLS renewal suddenly fails after months of quiet operation, server administrators often look first at rate limits or expired API credentials. On domains that rely on DNS-01 challenge validation—especially those issuing wildcard certificates—the root cause is frequently much simpler and quieter: dozens of old, orphaned _acme-challenge TXT records cluttering the authoritative DNS zone. Every time a renewal script crashes halfway through, encounters an API timeout, or lacks a proper cleanup hook, a token gets left behind. Over time, these abandoned records build up until the DNS response becomes too large or confused for the certificate authority to validate the fresh token. At the hosting support desk, this problem routinely surfaces when a domain fails its 60-day or 90-day automated renewal despite the server running the exact same configuration as before. The validation request begins, the ACME client creates a new TXT record, but the validation server reports that it found the wrong token or timed out trying to query the zone. Understanding how this accumulation happens and how to clear it out prevents emergency scrambles before certificates expire.
The ACME (Automated Certificate Management Environment) protocol relies on validation hooks to automate domain control checks. When using the DNS-01 challenge type, the client creates a TXT record with a cryptographic digest at _acme-challenge.example.com. Once the certificate authority queries your authoritative nameservers and validates the value, the client is supposed to run a cleanup routine to delete that specific TXT record via your DNS provider's API. When everything runs under ideal network conditions, this temporary record exists for only a minute or two. In practice, automation frequently breaks between the validation step and the cleanup step. If your ACME client—such as Certbot, acme.sh, or a web hosting control panel's internal AutoSSL daemon—hits a network timeout while talking to the CA, the script often terminates early with an exit error before executing the teardown routine. Similarly, if the DNS provider's API encounters rate limiting, HTTP 500 errors, or an authentication glitch right when the script attempts the deletion, the cleanup call fails silently or gets skipped entirely. The certificate request fails, but the record created during the attempt stays in your zone file permanently. Another frequent cause is human intervention during previous troubleshooting. When an administrator tests DNS-01 challenges manually using CLI flags like --manual, the tool instructs the operator to manually paste a TXT record into the DNS editor and press enter. Once the certificate issues, operators almost never go back into the DNS manager to delete that manual challenge record. Over several renewal cycles or failed debugging sessions, the zone quietly accumulates layers of dead validation tokens. For teams that previously moved between manual certificate management and automated tools, similar oversights often happen alongside authorization records, as explored in Fixing CAA Failures When Switching from Manual SSL to ACME Clients.
The ACME specification (RFC 8555) allows multiple TXT records to exist simultaneously under the _acme-challenge label. This design is necessary because a single certificate request covering multiple subdomains (such as example.com, *.example.com, and staging.example.com) requires distinct challenge tokens for each identifier, all sharing the same base record name. When the certificate authority's validation servers inspect the domain, they query for all TXT records at that name and scan the response array to see if the active challenge token is present. Failure occurs when the response becomes bloated with dozens of historical entries. Some certificate authority validation engines parse through returned entries sequentially, but they enforce strict timeouts on DNS resolution. If an authoritative nameserver returns twenty or thirty distinct TXT strings in a single payload, the CA's validator must process all of them. More critically, if older tokens belong to expired orders from months prior, any mismatch or parsing edge case in how the validator reads multiple identical keys can cause the validation worker to abort the check before finding the newly added valid hash. Furthermore, having stale records can mask propagation delays. When a new token is pushed, local caches or authoritative secondaries might continue serving an old record set. If the ACME client polls the nameservers locally before signaling the CA to proceed, it might read an old, stale TXT entry instead of waiting for the new one to fully propagate. The client mistakenly signals the CA that the record is ready, the CA queries the authoritative server, finds only the old tokens or an incomplete set, and permanently fails the authorization attempt for that cycle.
Yes, and this is the most destructive technical consequence of orphaned records. Standard DNS queries operate over UDP, which historically carried a strict payload size limit of 512 bytes. Extension Mechanisms for DNS (EDNS0) allow modern clients and servers to advertise larger buffer sizes—typically up to 1232 or 4096 bytes—to prevent packet fragmentation. However, each _acme-challenge TXT entry consumes approximately 43 characters for the digest itself, plus record labels, class, type, and TTL metadata. When a zone holds fifteen, twenty, or more orphaned entries, the total answer section easily exceeds standard UDP buffer allowances. When a UDP DNS response exceeds the client's advertised buffer size, the authoritative nameserver sets the Truncation flag (TC=1) in the response header. This flag tells the querying resolver that the answer was cut off and that the resolver must immediately retry the entire query over TCP port 53. While TCP fallback is a standard part of the DNS specification, it introduces noticeable latency. The validation resolver must now complete a full three-way TCP handshake before resending the query and receiving the payload. In many hosting environments, intermediate firewalls, cloud security groups, or enterprise edge proxies allow UDP port 53 traffic but silently block or throttle TCP port 53 traffic. When the authoritative server sets TC=1 and the CA's recursor attempts to fall back to TCP, the connection hangs and eventually returns a SERVFAIL or a query timeout. To the administrator looking at the ACME client output, the error simply says the domain could not be validated or that the nameserver was unreachable, hiding the fact that packet truncation caused the resolver to drop the request.
Before modifying your production DNS zone, inspect what external resolvers and your authoritative nameservers currently publish for your challenge hostname. You should direct the query straight to your domain's authoritative nameservers rather than a public caching resolver like 8.8.8.8 or 1.1.1.1, ensuring you see the true, un-cached state of the zone. Run a focused query against your authoritative server using dig to list all TXT entries currently active for the challenge path:
BASH
# Replace ns1.exampledns.com with your actual authoritative nameserver
# and example.com with your domain name.
dig @ns1.exampledns.com _acme-challenge.example.com TXT +noall +answer
If the command returns three, four, or dozens of separate lines containing old base64-encoded hashes, your zone contains orphaned records. If you are not actively running an ACME renewal command right at that second, every single one of those _acme-challenge TXT records is stale and safe to delete. To clean them up, log in to your DNS management interface—whether that is your domain registrar, cPanel Zone Editor, Route 53, Cloudflare, or a local BIND zone file—search for all TXT records where the name begins with _acme-challenge, and delete them. Do not delete other TXT records such as SPF, DKIM, or site verification strings that belong to your root domain or mail server; target only the specific _acme-challenge sub-label. Once removed, rerun the query above until the answer section returns completely empty (status: NOERROR with an empty answer section, or NXDOMAIN).
The permanent fix requires ensuring that your automation tools always clean up after themselves, even when a renewal fails. If you use a tool like Certbot with DNS plugins, verify that you are using an official, maintained plugin for your specific DNS provider rather than generic shell scripts that do not handle error catching. Maintained plugins register robust cleanup handlers that delete challenge entries during both successful issuances and unhandled exceptions. If your setup requires custom shell hooks using --manual-auth-hook and --manual-cleanup-hook, you must design the authentication script to be idempotent and the cleanup script to run unconditionally. A common design flaw in custom scripts is placing the deletion logic inside an if block that only fires when the entire certificate issuance succeeds. Instead, write the cleanup script so that it identifies the token by its value and calls the DNS API deletion endpoint regardless of whether the issuance passed or failed. Finally, for complex environments where multiple servers need certificates for subdomains of the same parent zone, consider delegating the challenge subdomain entirely using a CNAME record. By pointing _acme-challenge.example.com to an isolated, dedicated validation zone (such as an ACME-DNS instance or a secondary API-controlled zone), you keep your primary production zone file clean. Even if a script fails to delete a temporary hash in the dedicated challenge zone, your primary authoritative zone remains lean, fast, and free of DNS packet truncation issues.