Issue Description
When an ACME order fails after successful challenge validation, Stalwart logs nothing. The order is silently abandoned and a new one opened with a fresh token, looping indefinitely. The CA’s error response is not logged.
In this case the cause was a CAA record pinning issuance to a different ACME account via accounturi (this was set historically and never changed). Let’s Encrypt validated the DNS-01 challenge, then refused to issue a certificate.
The cause of this is definitely my fault (although I don’t understand why Stalwart didn’t overwrite the CAA record when it was set to, but that’s by the by), but the diagnosis took hours simply because the CA response wasn’t logged - even with the logs set to TRACE, there was no error message or any indication that there was a problem - all I saw was continual ACME retries a few minutes apart. A side effect of this is that this led to increasing timeouts being applied by Let’s Encrypt.
Expected Behavior
The CA’s rejection is logged, including its type and detail fields.
Order lifecycle events (order-created, authorization-valid, order-invalid, order-finalized) are emitted so the failing step is identifiable.
Repeated failures back off or stop rather than opening unbounded new orders against a CA that has already refused.
Actual Behavior
Everything Stalwart does log looked healthy throughout, which actively misled diagnosis:
Challenge TXT written and confirmed propagated within the configured timeout
Record publicly visible at the delegated authority, correctly RRSIG-signed
ad flag set when queried via 1.1.1.1
curl to the ACME directory endpoint returned 200
Reproduction Steps
Configure a domain for ACME with challengeType: Dns01 and automatic DNS management.
Publish a CAA record at the zone apex pinning a different ACME account:
example.com. IN CAA 0 issue “letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/OTHERACCOUNTID”
Trigger certificate issuance
Relevant Log Output
Failing loop — challenge propagates, order never progresses, new order opened
21:51:37 INFO ACME authentication started (acme.auth-start) hostname = “example.com”, type = “dns-01”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
21:51:37 INFO DNS record created (dns.record-created) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = [“nyrzOC6hoqgEspnyT0WZcMG0U5ylSne0bX25CmHAeNo”]
21:53:17 INFO DNS record propagated (dns.record-propagated) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = “nyrzOC6hoqgEspnyT0WZcMG0U5ylSne0bX25CmHAeNo”
← no acme.auth-pending, acme.auth-valid, acme.auth-completed, acme.order-ready, acme.order-valid, or any error
21:53:55 INFO ACME authentication started (acme.auth-start) hostname = “example.com”, type = “dns-01”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
21:53:55 INFO DNS record created (dns.record-created) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = [“okw0kH-rXOL9uNjtD4i1WjEhVHBg5n1soo00yzstHsM”]
21:55:05 INFO DNS record propagated (dns.record-propagated) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = “okw0kH-rXOL9uNjtD4i1WjEhVHBg5n1soo00yzstHsM”
21:56:15 INFO ACME authentication started (acme.auth-start) hostname = “example.com”, type = “dns-01”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
21:56:15 INFO DNS record created (dns.record-created) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = [“ucTrzeKNWnS6Hew_FR2ohnuG34KzFmMzIW03gKamQs4”]
21:58:15 INFO DNS record propagated (dns.record-propagated) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = “ucTrzeKNWnS6Hew_FR2ohnuG34KzFmMzIW03gKamQs4”
22:01:09 INFO ACME authentication started (acme.auth-start) hostname = “example.com”, type = “dns-01”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
22:01:09 INFO DNS record created (dns.record-created) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = [“RovrvBQgz3l10N7Dsks5I0fAT_82sV67J_MsHDYzJKA”]
Cause: CAA at the zone apex pinned a different ACME account via accounturi.
After relaxing CAA to 0 issue "letsencrypt.org", the same configuration succeeds
and the full order lifecycle is logged:
08:40:18 INFO ACME authentication started (acme.auth-start) hostname = “example.com”, type = “dns-01”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
08:40:18 INFO DNS record created (dns.record-created) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = [“Gco9J-d6OMcnDhqROXsqKOcOtqV2KDBV7FK-D2KfaFg”]
08:42:19 INFO DNS record propagated (dns.record-propagated) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = “Gco9J-d6OMcnDhqROXsqKOcOtqV2KDBV7FK-D2KfaFg”
08:42:22 INFO ACME authentication pending (acme.auth-pending) hostname = “example.com”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”, total = 0
08:42:26 INFO ACME authentication valid (acme.auth-valid) hostname = “example.com”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
08:42:27 INFO ACME authentication started (acme.auth-start) hostname = “example.com”, type = “dns-01”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
08:42:27 INFO DNS record created (dns.record-created) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = [“jv4rsJQ3uOpJbVcFWJRXDrABKu6Uivj9cMcBsPJeBS0”]
08:44:17 INFO DNS record propagated (dns.record-propagated) hostname = “_acme-challenge.example.com”, details = “example.com”, type = “TXT”, value = “jv4rsJQ3uOpJbVcFWJRXDrABKu6Uivj9cMcBsPJeBS0”
08:44:20 INFO ACME authentication valid (acme.auth-valid) hostname = “example.com”, url = “https://acme-v02.api.letsencrypt.org/acme/new-order”
08:44:20 INFO ACME authentication completed (acme.auth-completed) url = “https://acme-v02.api.letsencrypt.org/acme/new-order”, hostname = [“.example.com", “example.com”]
08:44:21 INFO ACME order ready (acme.order-ready) url = “https://acme-v02.api.letsencrypt.org/acme/new-order”, hostname = [".example.com”, “example.com”]
08:44:23 INFO ACME order valid (acme.order-valid) url = “https://acme-v02.api.letsencrypt.org/acme/new-order”, hostname = [“*.example.com”, “example.com”]
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
RocksDB
Blob Storage
Filesystem
Search Engine
Internal
Directory Backend
Internal
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on