CAA Record Blocks SSL Certificate Issuance

Custom domain on Vercel / Cloudflare / Firebase and the cert never issues? A leftover CAA record is locking out your host's CA. Here's the fast fix.

You bound a custom domain on Vercel, Cloudflare, or Firebase. DNS resolves, there’s no proxy in the way, but the SSL certificate just sits in “pending” or “generating” forever. If you can see provider logs they say something like CAA record prevents issuing the certificate or CAA record for yourdomain.com prevents issuance. The cause is almost always a CAA DNS record left over from a previous CA or registrar default, and it only allows a certificate authority your new host doesn’t use. The CA tries to issue, sees it isn’t on the allowlist, and stops. No retry loop, no loud error in the dashboard — just a cert that never appears.

Fastest fix: run dig CAA yourdomain.com +short. If it returns anything, either delete every CAA record (any CA can then issue) or add an issue record for your host’s CA. Vercel needs 0 issue "letsencrypt.org". Cloudflare and Firebase default to Google Trust Services, so add 0 issue "pki.goog; cansignhttpexchanges=yes" (Cloudflare’s own docs use that exact form — the bare pki.goog is not always enough). Wait for the TTL, then re-trigger issuance. Full diagnosis below.

Which bucket are you in?

SymptomLikely causeJump to
dig CAA returns issue records, host’s CA not listedRestrictive CAA from old setupCause 1
You never set CAA but dig shows recordsRegistrar / DNS provider defaultCause 3
Subdomain has no CAA, apex doesApex CAA inherits downCause 4
Only wildcard (*.) cert failsMissing issuewildCause 5
dig CAA SERVFAILs / DNSSEC errorsBroken DNSSEC blocks the CAA lookupCause 6
dig CAA returns nothing, cert still stuckNot a CAA problem — see RelatedRelated

Common causes

Ordered by hit rate, highest first.

1. CAA only allows a different CA

You (or a teammate) set CAA records months ago for security, for example 0 issue "digicert.com", meaning only DigiCert may issue. Then you moved to a host that uses a different CA. As of June 2026, Cloudflare and Firebase reach for Google Trust Services (pki.goog) by default, so a CAA that omits both Google Trust Services and Let’s Encrypt blocks them outright.

How to spot it:

dig CAA yourdomain.com +short

A restrictive set looks like:

0 issue "letsencrypt.org"
0 issue "digicert.com"

If your host’s CA isn’t in that list, issuance is blocked.

2. Host uses a CA you didn’t expect

Hosts change CAs over time, and many now use more than one. A CAA written two years ago may not allow the CA your host reaches for today.

  • Vercel issues exclusively via Let’s Encrypt. Any custom CAA on a Vercel domain must include 0 issue "letsencrypt.org".
  • Cloudflare can use Google Trust Services, Let’s Encrypt, SSL.com, or Sectigo. As of June 2026 its documented default is to always try Google Trust Services first and fall back to Let’s Encrypt only when a CAA record blocks Google (per Cloudflare’s SSL/TLS docs). So a Let’s-Encrypt-only CAA pushes Cloudflare onto Let’s Encrypt, but a CAA that allows neither blocks everything.
  • Firebase Hosting signs with either Google Trust Services (pki.goog) or Let’s Encrypt (letsencrypt.org), chosen automatically; with no CAA at all it can use both, and Firebase only surfaces a CAA prompt when it detects existing records that would block provisioning. Keep both values to let renewal pick whichever is healthy.
  • Netlify issues via Let’s Encrypt.

How to spot it: compare the issue values from dig CAA against the CA list above. If there’s no overlap, that’s your block.

3. CAA inherited from a registrar or DNS default

Some registrars and DNS providers add CAA for you. If you use Cloudflare as your DNS provider, it will even add CAA records on your behalf when it detects that your existing CAA would block all of its CAs — so you can end up with records you never typed.

How to spot it: even if you’re sure you never set CAA, run dig CAA yourdomain.com +short. A non-empty result means something or someone set defaults.

4. Apex CAA inherits to subdomains

CAA is climbed up the tree by the CA: if app.example.com has no CAA of its own, the CA checks example.com, then the parent of that, and so on. So even with app.example.com records correct, the apex’s CAA still governs the subdomain.

How to spot it:

dig CAA app.example.com +short
dig CAA example.com +short

If the subdomain returns nothing but the apex returns restrictive issue records, the apex CAA is what’s blocking you.

5. Wildcard cert needs issuewild

issue authorizes both regular and wildcard certs — unless an issuewild record also exists. Per RFC 8659, when any issuewild is present it takes precedence for wildcard (*.example.com) issuance and the issue records no longer apply to wildcards. So a domain that issues single-host certs fine can still fail wildcard issuance.

How to spot it: if only the wildcard cert fails, check for issuewild entries. Either remove them, or add an issuewild for your host’s CA, for example 0 issuewild "letsencrypt.org".

Also note: 0 iodef "mailto:..." is just an incident-reporting contact and never restricts issuance. Only issue and issuewild control whether a cert can be minted.

6. SERVFAIL on the CAA lookup (broken DNSSEC)

This one is new and easy to miss. Under the CA/Browser Forum’s Ballot SC-085v2, effective March 15, 2026, CAs must validate DNSSEC when it is present on the domain during the CAA and domain-control lookups. If your zone has DNSSEC enabled but broken (an expired RRSIG, a DS record at the TLD that doesn’t match your DNSKEY, or an unsupported algorithm), the CA’s validating resolver marks the answer BOGUS and returns SERVFAIL while looking up CAA, and issuance is refused even though your CAA values are fine. Domains with no DNSSEC at all are unaffected by this rule.

How to spot it:

dig CAA yourdomain.com +dnssec

A SERVFAIL status, or a missing ad (authenticated-data) flag combined with a published DS record, points at DNSSEC, not at the CAA contents. Fix the DNSSEC chain (see DNSSEC validation failure) before touching CAA values.

Shortest path to fix

Step 1: List every existing CAA record

dig CAA yourdomain.com +short
dig CAA www.yourdomain.com +short    # subdomain may have its own

Write down every issue and issuewild value. If both come back empty, CAA is not your problem — skip to Related.

Step 2: Find which CA your host uses

From the research above, as of June 2026:

HostCertificate authorityCAA issue value to allow
VercelLet’s Encryptletsencrypt.org
CloudflareGoogle Trust Services (default), falls back to LE; also SSL.com / Sectigopki.goog; cansignhttpexchanges=yes, plus letsencrypt.org ssl.com sectigo.com to be safe
Firebase HostingGoogle Trust Services + Let’s Encrypt (auto-chosen)pki.goog and letsencrypt.org
NetlifyLet’s Encryptletsencrypt.org

For Cloudflare specifically, its docs publish the records it expects, and for Google Trust Services that includes the cansignhttpexchanges=yes flag and a matching issuewild. If your host isn’t listed, open a support ticket and ask plainly: “Which CA do you use for SSL on custom domains?”

Step 3: Either add the host’s CA, or remove CAA

Option A — add your host’s CA(s):

yourdomain.com    CAA    0 issue "letsencrypt.org"
yourdomain.com    CAA    0 issue "pki.goog; cansignhttpexchanges=yes"
yourdomain.com    CAA    0 issue "sectigo.com"
yourdomain.com    CAA    0 issue "ssl.com"

Keep your existing entries and add the ones your host needs. Listing several CAs is fine and is the safer choice if your host can pick from a pool (Cloudflare). Note the Google Trust Services value carries the cansignhttpexchanges=yes parameter — that is the exact string Cloudflare’s docs use, and dropping it is a common reason a pki.goog CAA still gets rejected. If you also serve a wildcard cert and have any issuewild record, add a matching issuewild line for the same CA, for example 0 issuewild "pki.goog; cansignhttpexchanges=yes".

Option B — remove CAA entirely:

Delete all CAA records. With no CAA, any publicly-trusted CA may issue. This is simpler and fine for most sites; you lose the (small) protection CAA gives against mis-issuance.

Note on Vercel specifically: if your domain points at Vercel via their CNAME, you inherit Vercel’s CAA and can’t set your own at that subdomain. To control CAA yourself, switch from the CNAME to Vercel’s A record, then add 0 issue "letsencrypt.org".

Step 4: Wait for the TTL, then verify propagation

CAA changes propagate on the record’s TTL; allow up to a few hours, and up to 24h in stubborn cases. Verify against multiple public resolvers:

dig CAA yourdomain.com @8.8.8.8 +short
dig CAA yourdomain.com @1.1.1.1 +short

Both should return your new values. If one still shows the old set, it hasn’t propagated; don’t re-trigger issuance yet.

Step 5: Re-trigger certificate issuance

Most dashboards expose a “Retry”, “Refresh”, or “Remove and re-add domain” action. Trigger it once. Don’t hammer it — CAs apply rate limits (Let’s Encrypt allows a limited number of failed validations per account/hostname per hour), and repeated remove/re-add can lock you out for the rest of the hour. Once per hour at most while you wait.

Step 6: Confirm it’s fixed

curl -sI https://yourdomain.com | head -3

You want HTTP/2 200 with no TLS error. Then confirm the issuing CA matches what you allowed:

echo | openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -issuer -dates

The issuer= line should name the CA you authorized (for example Let's Encrypt or Google Trust Services), and notBefore should be recent. In a browser you can also click the padlock and read the certificate’s issuer and validity dates.

Prevention

  • Before switching hosts, look up which CA they use and update CAA in the same change window.
  • Don’t set restrictive CAA unless you have a real security reason; no CAA at all is fine for most sites.
  • For subdomains, remember the apex CAA inherits down — fix it at the apex, or override per-subdomain.
  • After any CAA change, wait out the TTL and verify with two public resolvers before re-triggering issuance.
  • Keep DNSSEC healthy; since the CA/Browser Forum’s Ballot SC-085v2 took effect March 15, 2026, a broken DNSSEC chain blocks issuance via SERVFAIL on the CAA lookup even when your CAA values are correct.
  • Record why each CAA entry exists in your DNS notes so a future you doesn’t trip over it.

FAQ

Do I even need a CAA record? No. CAA is optional. With no CAA record, any publicly-trusted CA may issue for your domain. CAA only adds value if you want to restrict issuance to specific CAs for security or compliance.

I deleted my CAA records but the cert still won’t issue. Why? Either the change hasn’t propagated (re-check with dig ... @8.8.8.8 +short against your old TTL), or the block was never CAA. If dig CAA now returns empty everywhere and issuance still fails, look at DNSSEC SERVFAILs, the actual A/AAAA/CNAME target, or domain-control validation — see SSL cert delay.

Which CAA value does Vercel need? 0 issue "letsencrypt.org". Vercel issues only through Let’s Encrypt, so any custom CAA on a Vercel domain must include that line.

Cloudflare keeps telling me to switch to Google Trust Services — what CAA do I add? Add 0 issue "pki.goog; cansignhttpexchanges=yes" (and 0 issuewild "pki.goog; cansignhttpexchanges=yes" if you serve a wildcard). That is the exact form in Cloudflare’s CAA docs; the bare pki.goog is a frequent cause of a CAA that still fails. As of June 2026 Cloudflare tries Google Trust Services first and only falls back to Let’s Encrypt when CAA blocks Google, so keeping letsencrypt.org, ssl.com, and sectigo.com as well lets it pick across its pool.

My single-host cert works but the wildcard fails. What’s different? You almost certainly have an issuewild record that excludes your host’s CA. Per RFC 8659, issuewild overrides issue for wildcard certs. Add a matching 0 issuewild "yourca.tld" or remove the issuewild records.

My CAA values look correct but the CA still reports a SERVFAIL on the CAA lookup. What now? Since March 15, 2026, if DNSSEC is enabled on your zone but broken, the CA’s resolver returns SERVFAIL during the CAA check and refuses to issue. Run dig CAA yourdomain.com +dnssec: a SERVFAIL status, or a missing ad flag while a DS record is published, points at DNSSEC, not the CAA contents. Fix the chain (or, if you don’t need DNSSEC, remove the DS record at your registrar and disable DNSSEC) before retrying. See DNSSEC validation failure.

How long should I wait after changing CAA? Allow at least the record’s TTL, commonly minutes to an hour. Give it up to 24h before concluding it failed, and confirm with two independent resolvers before re-triggering.

Tags: #Troubleshooting