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?
| Symptom | Likely cause | Jump to |
|---|---|---|
dig CAA returns issue records, host’s CA not listed | Restrictive CAA from old setup | Cause 1 |
You never set CAA but dig shows records | Registrar / DNS provider default | Cause 3 |
| Subdomain has no CAA, apex does | Apex CAA inherits down | Cause 4 |
Only wildcard (*.) cert fails | Missing issuewild | Cause 5 |
dig CAA SERVFAILs / DNSSEC errors | Broken DNSSEC blocks the CAA lookup | Cause 6 |
dig CAA returns nothing, cert still stuck | Not a CAA problem — see Related | Related |
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:
| Host | Certificate authority | CAA issue value to allow |
|---|---|---|
| Vercel | Let’s Encrypt | letsencrypt.org |
| Cloudflare | Google Trust Services (default), falls back to LE; also SSL.com / Sectigo | pki.goog; cansignhttpexchanges=yes, plus letsencrypt.org ssl.com sectigo.com to be safe |
| Firebase Hosting | Google Trust Services + Let’s Encrypt (auto-chosen) | pki.goog and letsencrypt.org |
| Netlify | Let’s Encrypt | letsencrypt.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.
Related
- SSL cert delay
- DNS changed site still down
- Wildcard DNS not matching subdomain
- Custom domain works on Vercel but not Firebase
- Site Opens Intermittently After Domain Connect
- SSL Mixed Content Warning in Browser
- Cert Rejected: Certificate Transparency Log Mismatch
- Cloudflare Orange Cloud vs Grey Cloud: Wrong Toggle Breaks Site
- DNSSEC Validation Fails After Enabling at Registrar
- HSTS Preload Stuck: Can’t Roll Back HTTPS Even After Removal
- IPv6 Users Can’t Reach Site: AAAA Record Missing or Broken
- Subdomain NS Delegation Fails: Missing Glue Records
Tags: #Troubleshooting