HTTP 522 after pointing a domain at Cloudflare Pages (and the Search Console fallout)
What I did, and what broke
Migrating a static site to Cloudflare Pages, in this order:
POST /accounts/{id}/pages/projects— create projectwrangler pages deploy public --project-name …— upload, deployment succeededPOST /accounts/{id}/pages/projects/{p}/domains— addsite.example.com- immediately repoint the DNS record to
<project>.pages.dev, proxied
Seconds later:
$ curl -sSI https://site.example.com/
HTTP/2 522
server: cloudflare
cf-ray: a3664d60bfb3386b-LHR
The domain was serving Cloudflare’s “connection timed out” error, because the Pages side had not finished attaching it:
GET …/pages/projects/site/domains
site.example.com status=pending validation=pending cert=lets_encrypt
About a minute later the same query returned status=active validation=active, and the site answered
200. Total outage: under two minutes, on a site with no users yet.
Why it happens
Adding a custom domain to a Pages project starts two asynchronous processes: attaching the hostname to the project’s routing, and issuing the certificate. Until the hostname is attached, Cloudflare’s edge is already authoritative for the name (your DNS record points at it) but has no origin to serve — hence 522, not a DNS error.
So the ordering rule is: flip DNS only after the Pages domain reports active.
until curl -sS -H "Authorization: Bearer $CF_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACC/pages/projects/$PROJ/domains" \
| jq -e '.result[] | select(.name=="site.example.com" and .status=="active")' >/dev/null
do sleep 10; done
# now update the DNS record
The exception: a hostname Cloudflare cannot pre-validate
The wait-for-active rule only works when Cloudflare can validate the hostname while your DNS still
points elsewhere. If a conflicting record already exists — for example an A record for the apex
pointing at old parking or another host — validation stays pending indefinitely:
jofrey.eu status=pending validation=pending
www.jofrey.eu status=pending validation=pending
Cloudflare is waiting for the record to point at the project, and the project is waiting for validation. In that case the DNS change has to come first, and a short 522 window is unavoidable:
poll 1: jofrey.eu=pending root/ads.txt=522
poll 2: jofrey.eu=pending root/ads.txt=200 # edge picked up the project
...
poll 11: jofrey.eu=active www.jofrey.eu=active # certificate issued (~3.5 min later)
So the honest rule is: wait for active when you can, and when you cannot, schedule the switch for a
window where a couple of minutes of errors costs nothing — and expect external crawlers to catch you if
it does not.
On a live site, do it the other way round entirely: attach the custom domain while DNS still points at the
old host, wait for active, then switch. Cloudflare will not serve the hostname before it is attached, so
there is no conflict in waiting.
The part that outlived the outage
The site was healthy within two minutes, but Google Search Console kept showing:
/sitemap.xml Last read: 05/09/2026 Status: Sitemap could not be read Discovered pages: 0
Googlebot had fetched during the 522 window and got an HTML error page instead of XML. Search Console caches that failed attempt and does not retry promptly, so the sitemap looked broken long after the cause was gone. Everything checked out on my side:
- no BOM (
3c3f 786d 6c=<?xml),content-type: application/xml - Brotli-encoded response byte-identical to the identity encoding after decode
- valid
urlsetnamespace, parsed by two XML parsers URL Inspection → Test live URLreported Page fetch: Successful, Indexing allowed: Yes
The fix was to submit the sitemap under a URL with no failure history — sitemap.xml?v=2, same file,
new row — which immediately reported Success, 18 discovered pages.
Takeaways
- Sequence async operations, do not overlap them. “Create resource, then point traffic at it” needs a readiness check between the two steps, exactly like waiting for a health check before shifting a load balancer.
- A two-minute outage can leave multi-day artefacts in external systems that cache their view of you. When something external claims your site is broken, check whether it is reporting a stale observation before you start changing configuration.
- Query-string variants are a cheap way to get a fresh evaluation from a tool that has cached a failure for a URL.