errno

HTTP 522 after pointing a domain at Cloudflare Pages (and the Search Console fallout)

· tested on Cloudflare Pages, custom domain on a zone in the same account, Google Search Console

What I did, and what broke

Migrating a static site to Cloudflare Pages, in this order:

  1. POST /accounts/{id}/pages/projects — create project
  2. wrangler pages deploy public --project-name … — upload, deployment succeeded
  3. POST /accounts/{id}/pages/projects/{p}/domains — add site.example.com
  4. 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:

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

cloudflare pages dns seo