certbot / certbot/certbot

[Bug]: Intermittent dns-01 validation failures after upgrade to Python 3.13 + acme 5.2.x

Open
#10,537 1 comment 0 reactions 1 assignee Claimed by @wgreenberg View on GitHub
Dominant language
Python
Stars
33.2k
Forks
3.5k
Avg merge
6d 10h
Merged PRs (30d)
3

Description

### OS

Python 3.13 Container

### Installation method

pip

### Certbot Version

5.2.x

### What happened?

Summary
We orchestrate Let’s Encrypt certificate renewals using Python and the acme module. After upgrading to Python 3.13 and acme 5.2.2 (also tested 5.1.0), we started seeing intermittent dns-01 validation failures. The same logic has been stable for years on Python 3.9 with acme 1.22.

Environment

Python: 3.13
acme: 5.2.2 (also tried 5.1.0; previously stable on 1.22)
DNS: OpenStack Designate
Certificate type: wildcard (*.vlab.crm.example.com)
Challenge: dns-01, TXT at _acme-challenge.vlab.crm.example.com
Deadline passed to poll_and_finalize: 5 minutes
Observed behavior

We create the TXT record and verify it across multiple public resolvers (8.8.8.8, 8.8.4.4, 1.1.1.1, 9.9.9.9) and our internal resolvers.
Despite this, poll_and_finalize sometimes returns almost immediately with:
acme.errors.ValidationError: Authorization failed: Challenge dns-01 failed with error urn:ietf:params:acme:error:unauthorized :: No TXT record found at _acme-challenge.vlab.crm.example.com
Example timing from logs:
16:12:34.721: TXT record created and “validated successfully” by our checks
16:12:34.721: deadline set to 16:17:34.721
16:12:36.145: poll_and_finalize fails with ValidationError

It is failing in less than 2 seconds.

Questions

Is acme 5.x expected to return immediately once the server marks the authorization invalid, even if a deadline is provided?
Are there known changes to poll_and_finalize/poll_authorizations behavior between acme 1.22 and 5.x that could explain quicker failure on transient DNS propagation/negative caching?
Do you have guidance on mitigating resolver-side negative caching (e.g., NXDOMAIN caching) that might cause Let’s Encrypt’s resolvers to miss newly created TXT records?
Would you recommend pre-creating the _acme-challenge label (to avoid NXDOMAIN), reducing SOA negative TTL, or delaying finalize after TXT publication?

Thank you for any pointers or known best practices to avoid these intermittent failures.

Zareh

### Expected behavior

After publishing the TXT record, we expect the authorization to remain pending until the record is visible to Let’s Encrypt’s resolvers, or at least for the client to continue polling until the deadline before concluding failure.

Notes and history

This issue started after upgrading to Python 3.13 + acme 5.2.x; the same workflow does not exhibit this behavior on Python 3.9 + acme 1.22.
The failures are intermittent. In many runs, validation succeeds using the same logic.
We are not using CNAME indirection for the challenge; we publish TXT directly at _acme-challenge..

### Relevant log output

```shell
2026-01-16 16:12:34.721 - DNS record _acme-challenge.vlab.crm.example.com validated successfully
2026-01-16 16:12:34.721 - DNS challenge for *.vlab.crm.example.com created and validated
2026-01-16 16:12:34.721 - Validation retrieval deadline set to 2026-01-16T16:17:34.721
2026-01-16 16:12:36.145 - ACME ValidationError: dns-01 failed: No TXT record found
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.