CustomDomain docs

Troubleshooting

Common failure modes — stuck connections, propagation delays, rail errors, and drift.

A connection is waiting in pending

pending means we have not yet seen the DNS records in public DNS. There is no deadline — a pending connection is re-checked every minute at first, then every few minutes, and after three days every six hours, for as long as it takes. Add the records whenever you're ready and the domain connects on its own. After three days the console shows "We haven't detected the DNS records yet" so you know what's outstanding; that is a diagnosis, not a failure.

To check right now instead of waiting: Re-check now on the domain page (POST /v1/connections/{id}:recheck). It reports each record's verdict.

Common reasons the records never show up:

  • The record was added at the wrong place. Records must be added at the provider that serves the domain's nameservers (dig NS your-domain.com), which is not always the registrar you bought the domain from.
  • Root domain on GoDaddy, Namecheap or Name.com. These panels have no ALIAS/ANAME type, so the console shows A records to our apex addresses instead of a CNAME. Add exactly those A records at @. (A CNAME at @ is rejected by the panel, or breaks your email.)
  • The domain doesn't resolve at all — unregistered, or registered but never delegated to a DNS provider. The connect flow now refuses these up front with an explanation; fix the delegation at your registrar first.
  • A hosting platform's subdomain (something.vercel.app, *.netlify.app, *.github.io, …) can't be connected: the platform owns its DNS. Use a domain you control.

My domain points at Custom Domain but shows a connection / certificate error

If you added the DNS records after the connection had been marked failed, visitors' browsers reach our edge but the connection isn't serving yet. Since this release the edge treats that traffic as your signal: the connection is re-entered into verification automatically and goes live on the next check (usually within a minute or two). You can also press Re-check now. If it stays failed, the domain already has another active connection in the same application — finish or delete that one.

"Failed" — what it means now

A connection only reaches failed when records we wrote ourselves never propagated (24h), or a credentialed write was rejected. Never because you were slow. Finish setup on the domain page resumes a failed connection (same row, history kept); adding the same domain again does the same thing rather than creating a duplicate.

Verification links last one hour and work once. On the Check your email screen use Resend the link; an expired link lands on a page where you can request a new one. Still nothing? Check spam, then email [email protected] and we'll verify you by hand.

GoDaddy won't give me an API token

GoDaddy only issues DNS API access to accounts with 10+ domains or a paid plan. Everyone else: add the records shown in the console by hand — that path works on every GoDaddy account. GoDaddy's "sign in with GoDaddy" one-click setup also isn't available yet (it requires GoDaddy-side onboarding).

Route 53: "The security token included in the request is invalid"

You pasted temporary credentials (an access key starting with ASIA…). Those need the third field, Session token, which the Route 53 form now has. Permanent IAM-user keys (AKIA…) don't need it.

A connection is stuck in propagating

Records were written but aren't all resolving to their intended values yet.

  • DNS propagation can take minutes to hours depending on the previous record's TTL and the customer's resolver/registrar.
  • Verify the records at the provider's dashboard — a rail write can succeed at the API but land on the wrong host, or a customer may have edited them afterward.
  • propagating connections that never resolve within 24 hours transition to failed and fire connection.failed.

service_unavailable on a rail

POST /v1/connections/{id}/apply (and the OAuth / one-click setup starts) return 503 service_unavailable when the corresponding engine isn't wired for your plan or environment: no DNS provider registry, no OAuth client for the provider (OAUTH_<PROVIDER>_CLIENT_ID/_SECRET), or no one-click signing key (DC_SIGNING_KEY_FILE). Contact support if you hit this on the hosted service.

Rail B write failed

apply returns an error carrying the provider's message when the scoped token is wrong-scoped, expired, or the zone doesn't match. Confirm the token has DNS edit rights on the exact zone you passed, and mind provider gates (GoDaddy account tier, Namecheap IP allowlist) — see Provider setup.

OAuth (Rail C) never returns

  • PopupBlockedError — the browser blocked the authorize window; trigger oauth:start from a direct user gesture.
  • The callback only postMessages to a return_origin on the server's allowlist (OAUTH_ALLOWED_RETURN_ORIGINS) — a mismatched origin silently drops the result.
  • An expired or replayed state returns 400 from the callback; re-run oauth:start to get a fresh one.

A live domain stopped working

The lifecycle doesn't demote a live connection, but Monitor fires domain.record_missing when a live domain's records stop resolving. Have the customer restore the records (or re-apply them via a rail). Run POST /v1/monitor:check to compare on demand.

Certificate not issuing

Certificates are issued on demand at the TLS handshake, gated by POST /internal/ask returning { approved: true } — which happens only once the connection is propagating or live. If the edge can't reach the gate, check EDGE_ASK_URL, EDGE_ASK_SECRET, and EDGE_ACME_PROD/EDGE_ACME_EMAIL.

Widget shows "session expired"

Widget tokens expire (default 60 minutes — see Widget tokens). Mint a fresh token server-side and reopen the widget.

On this page