Troubleshooting guide

Custom domain not working but the platform URL works

The deployment is healthy on the host's own address and broken on your domain. In our data this is the largest single group: 41 verified builder reports covering redirect loops, 500s, 404s, stalled downloads, TLS failures and certificates that expired after renewal quietly stopped working. The app is rarely the cause. The domain is a separate system with its own state.

41 verified cases11 min read Updated 8 Oct 2026How we collect cases

What you'll see

  • The platform address (for example name.vercel.app or name.netlify.app) works, and your custom domain returns a 500 or 404.
  • The browser reports a redirect loop (ERR_TOO_MANY_REDIRECTS) on the custom domain only.
  • HTTPS fails with a protocol error or a handshake reset, on some devices or networks, even though the dashboard shows a certificate.
  • The certificate is about to expire, or has expired, and the platform says renewal or validation is failing.
  • The domain dashboard is stuck on pending verification for a day or more while the DNS records look correct.
  • You cannot add the domain to a new project because it is still attached to an old account, or to the wrong project.

Why it happens

Cause 1

The proxy and the origin disagree about HTTP and HTTPS

With Cloudflare in Flexible mode, the visitor reaches Cloudflare over HTTPS but Cloudflare calls the origin over HTTP. If the origin redirects every HTTP request to HTTPS, the browser is sent round in a circle. Vercel documents this case. The reverse also loops: in Full or Full (strict) mode, an origin that redirects HTTPS back to HTTP creates the loop. MDN notes that a server that detects a loop may answer with a 500, so treat a 500 right after a redirect change as a possible loop first.

Cause 2

The certificate validation path is closed to the CA

Issuance and renewal both require the certificate authority to verify that you control the domain, by an HTTP token or a DNS TXT record. A proxy that challenges, caches or redirects the validation URL, or a Worker route that matches it, blocks that check. Cloudflare lists WAF rules, Under Attack mode, Workers routes and redirects on /.well-known/* among the blockers. Vercel's reverse-proxy guidance says to keep HTTP-to-HTTPS redirection off for /.well-known/acme-challenge/* on port 80 and to keep that path uncached, for renewals as well as first issuance.

Cause 3

Stale or conflicting DNS records

Old A or AAAA records, a leftover _acme-challenge TXT record from a previous provider, an NS record that hands the name to another DNS host, CAA records that exclude the issuing CA, or a broken DNSSEC chain can each stall validation. Cloudflare notes that HTTP validation prefers IPv6, so an AAAA record that points somewhere different from the A record can cause failure. Netlify adds that old cached records must reach the end of their TTL before new settings can validate.

Cause 4

The domain is attached to another account or project

A domain can belong to only one account or team on Vercel at a time. A domain left on a former account, or added to the wrong project, blocks the real one until it is moved or ownership is re-verified. If you own the domain but not the other account, Vercel offers a TXT-record check.

Cause 5

Retrying after failures hits certificate authority rate limits

Let's Encrypt allows 5 authorization failures per identifier per account per hour and 5 certificates for the same set of names every 7 days. Non-ARI renewals still count against both limits. Repeated manual retries against an unfixed cause can block issuance for days, and those two limits have no override.

How to fix it

  1. Compare the platform address with the custom domain

    Request both and compare status, Location and Server headers before changing anything. If one stalls or truncates and the other does not, test IPv4 and IPv6 separately to see whether the two hostnames take different network paths. We found no single documented cause for stalled or truncated responses, so treat the result as a way to isolate the problem, not a diagnosis.

    curl -sSI https://your-app.vercel.app | head -20
    curl -sSI https://example.com | head -20
    curl -4 -sS -o /dev/null -w '%{size_download}\n' https://example.com/app.js
    curl -6 -sS -o /dev/null -w '%{size_download}\n' https://example.com/app.js
  2. Check DNS against what the platform asks for

    Read the records the host shows in its domain settings and compare them with what resolves. Remove outdated A, AAAA or CNAME records, make the AAAA record match the A record's destination or delete it, and look for stray NS and CAA records.

    dig +short A example.com
    dig +short AAAA example.com
    dig +short CNAME www.example.com
    dig +short NS example.com
    dig CAA example.com +noall +answer
  3. Fix the proxy's connection to the origin

    For a redirect loop behind Cloudflare, set SSL/TLS to Full (strict) with a valid certificate on the origin, or remove the origin's HTTPS redirect if you must stay on Flexible. Remove any origin rule that sends HTTPS back to HTTP, and check Redirect Rules and Page Rules for two rules pointing at each other. Vercel's own HTTP-to-HTTPS redirect cannot be disabled, so on Vercel the proxy has to connect over HTTPS.

  4. Keep the validation path open, including for renewals

    On port 80, let /.well-known/acme-challenge/* (and /.well-known/pki-validation/* on Cloudflare) through without caching, authentication, rewrites or redirects. In a Cloudflare HTTP-to-HTTPS Redirect Rule, exclude the path with: (http.request.scheme eq "http") and not starts_with(http.request.uri.path, "/.well-known/"). If the proxy cannot be made transparent, point DNS straight at the host (DNS only in Cloudflare), as both Vercel and Netlify advise for issuance.

  5. Clear stale validation records and resolve ownership

    Look for a leftover challenge TXT record from a previous provider, and keep any NS record that deliberately delegates validation. If the platform says another account owns the domain, move it from that account, or use the host's external-connect option and add the TXT record it gives you.

    dig +short TXT _acme-challenge.example.com
  6. Fix the cause before you retry issuance

    Run a public checker such as Let's Debug or DNSViz, correct what it finds, then trigger issuance once. If you are already rate limited, wait out the window or switch to another CA where your plan allows it. Cloudflare says most Let's Encrypt limits clear within 7 days.

  7. Record the owner and alert before expiry

    Write down which account holds the domain, the DNS host, and how renewal validates (HTTP token, TXT record, or delegated validation). Add an expiry check that fires weeks ahead, not days. Cloudflare issues renewal tokens 30 days before expiry, so a failed HTTP renewal can be caught well before the certificate expires.

    echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate

Check it's fixed

  • curl -sSI https://example.com returns the same status as the platform address and no Location header pointing back at itself.
  • The host's domain page shows the certificate as issued or active, and openssl reports an expiry date well in the future.
  • curl -sI http://example.com/.well-known/acme-challenge/test is not redirected to HTTPS and not blocked by a challenge page. A made-up token normally returns 404.
  • dig shows no stale A, AAAA, NS or _acme-challenge records, and the AAAA record matches the A record or is absent.

Fix it with Gemmein

On Gemmein a domain is verified only when Gemmein finds its DNS records, never because a provider said so, and a domain another app has already proved is refused as a conflict and recorded in Logs. A browser calling from an https address that is not on the Domains page is refused 403 origin_not_allowed, naming the address, and Problems lists such addresses.

  1. Add the domain you own on the Domains page

    For web, Gemmein gives one record to publish (for email, five, receiving included). A host's preview address such as name.vercel.app is refused preview_address.

  2. Publish the records with Connect automatically or by hand

    When your DNS is run by a provider that has approved Gemmein's template (Cloudflare first), Connect automatically lets you see the exact records and approve them at the provider, and Gemmein never holds a login or token for your DNS. If your provider does not support Connect automatically, the Records list shows each record with the exact name your provider wants and whether it is found, missing or has the wrong value.

  3. Let your AI tool read the DNS state

    When your AI needs your DNS state it runs npx gemmein domains and asks you only for records not found yet. Until the records are found the domain stays pending, and the page checks every minute while a record is still waiting.

    npx gemmein domains
  4. Check Problems for refused browser addresses

    A browser call from an https address that is not on the Domains page is refused 403 origin_not_allowed, naming the address. Problems lists such addresses (up to five shown); add the domain.

Questions

Why does name.vercel.app work but my own domain does not?

The platform address is served on the host's own DNS and certificate. Your domain adds separate DNS records, possibly a proxy, and its own certificate issuance. Compare those three before touching application code.


Does Cloudflare's Always Use HTTPS stop certificate renewal?

Cloudflare's documentation says Always Use HTTPS does not impact the validation process. Redirect Rules or origin redirects that catch /.well-known/* can, so exclude that path from them.


Do I need a CAA record?

Vercel states that having no applicable CAA records does not block issuance. If you do publish CAA records, they must authorize the issuing CA, for example 0 issue "letsencrypt.org" for Let's Encrypt, and wildcard certificates follow issuewild when present.


How long should I wait after a DNS change?

Vercel says standard records such as A, CNAME and TXT typically propagate faster, while a nameserver change can take 24 to 48 hours. Lowering the TTL before a planned change makes a rollback quicker.


Why do wildcard certificates keep failing when other names renew?

Wildcard certificates need DNS-01 validation, so the platform must be able to create a TXT record each time. Use the host's nameservers, or delegate the _acme-challenge name to it as Vercel documents.


Sources

← Back to the full report