[Bug] Custom domain returns 404 NOT_FOUND — edge routing entry missing

Subject: Custom domain aiwebcool.com returns 404 NOT_FOUND globally — edge routing entry missing (project serves fine via .vercel.app)

Hi Vercel support,

My custom domain aiwebcool.com returns 404 NOT_FOUND (X-Vercel-Error: NOT_FOUND)
from Vercel’s edge worldwide, despite the configuration being completely correct.
The edge routing entry for the custom domain appears to be missing/broken and is
not being created by any control-plane operation. I’ve exhausted all client-side
remediation and need your help to force-refresh the edge routing.

Project: aiweb
Team: annygoids-projects
Custom domain: aiwebcool.com

== Configuration is correct (verified) ==

  • aiwebcool.com is added to project aiweb, verified, and shows “Valid Configuration”
    in the dashboard (no red error, no Retry button).
  • vercel domains verify returns: configured-correctly, project.attached: true,
    project.verified: true, misconfigured: false.
  • The domain is aliased to a Ready production deployment (confirmed via
    vercel inspectaiwebcool.com is in the deployment’s alias list).
  • DNS: Cloudflare CNAME @ → 92f6e9970d83415e.vercel-dns-017.com., DNS-only
    (proxy off / grey cloud). Resolves to Vercel edge IPs.
  • Only one team (annygoids-projects) and one project (aiweb) exist; no duplicate
    or personal-account project conflict.

== Proof the issue is custom-domain edge routing, not DNS / config / deployment / code ==

  1. The project’s .vercel.app domain (aiweb-annygoids-projects.vercel.app) serves
    correctly — HTTP 302 Found from 8 worldwide test nodes (check-host.net). So the
    project and its deployments work.
  2. The custom domain aiwebcool.com returns 404 NOT_FOUND from 12 worldwide test
    nodes (check-host.net) — US, CA, EU, Asia, Middle East all 404. This is global,
    not a regional propagation issue.
  3. curl --resolve aiwebcool.com:443:76.76.21.21 https://aiwebcool.com/ (bypassing
    DNS and Cloudflare, SNI=aiwebcool.com, direct to a Vercel edge IP) STILL returns
    X-Vercel-Error: NOT_FOUND. This rules out DNS, Cloudflare, proxy, and local
    network — the Vercel edge itself does not route aiwebcool.com.
  4. SSL certificate is validly issued. Verified via
    openssl s_client -servername ``aiwebcool.com`` -connect 76.76.21.21:443:
    subject CN=aiwebcool.com, issuer Let’s Encrypt (YR2), valid Jul 19 – Oct 17 2026.
    So this is NOT a certificate/SNI issuance problem; TLS handshake succeeds and the
    404 is returned post-TLS.
  5. The app is fully static (SSG, no server functions). There is no middleware.ts and
    no vercel.json with host-based logic, so the 404 cannot originate from my code.
    The request is dropped at the Vercel edge/gateway before reaching any deployment.
  6. The response is a bare 404 NOT_FOUND (79-byte plain text, edge-level), not a 3xx —
    so it is not a redirect/primary-domain misconfiguration.

== What I already tried (none populated the edge routing) ==

  • vercel deploy --prod (CLI production deploy — domain auto-aliased)
  • vercel domains rm + vercel domains add (remove & re-add the domain)
  • vercel alias rm + vercel alias set (re-alias to the Ready production deployment)
  • Git push to main to trigger a git-based production build (deployment Ready, domain
    auto-followed)
  • DNS changes: A records ↔ CNAME, Cloudflare proxy on ↔ DNS-only
  • Full ghost-domain reset: removed the domain from Vercel, removed the DNS records in
    Cloudflare, waited 18 minutes for edge cache expiry, then re-added the domain in
    Vercel first and re-added the DNS CNAME (DNS-only) afterwards. vercel domains verify returned to configured-correctly, but the edge STILL returns
    X-Vercel-Error: NOT_FOUND via curl --resolve.

== Conclusion ==
The control plane (API + dashboard) has the custom domain correctly attached,
verified, and aliased to a Ready production deployment, with a valid SSL certificate.
The data plane (edge routing table) has no entry for aiwebcool.com, while the
.vercel.app aliases route correctly. This has persisted for ~2 hours across every
re-push method and is not a propagation delay.

== Request ==
Could you force-refresh / recreate the edge routing entry for aiwebcool.com
project aiweb (team annygoids-projects)?

Thank you.

There’s another community post with 404 debugging tips that might be helpful. Please give these solutions a try and let us know how it goes.

A human should be around soon to offer more advice. But you can also get helpful information quickly by asking v0.

“Thank you v0, but I have already thoroughly ruled out all client-side and code-level issues (DNS, SSL, vercel.json, SPA rewrites, deployment output). The deployment works perfectly on the .vercel.app URL.
As confirmed by previous diagnostics, this is strictly a platform-level Edge Routing desync. The control plane shows the domain aiwebcool.com as valid, but the data plane returns X-Vercel-Error: NOT_FOUND.
Please escalate this to a human engineer to force-refresh the edge routing entry for my domain.”

Hi Annygoid,

Your curl --resolve test is the strongest signal here. If the .vercel.app deployment works, TLS for aiwebcool.com completes, and a direct request with SNI aiwebcool.com to a Vercel edge IP still returns X-Vercel-Error: NOT_FOUND, then this looks past normal DNS propagation, Cloudflare proxying, or SSL issuance.

I’d make the repro package as small and stable as possible now, and avoid more DNS flips while it’s being investigated:

curl -sSI https://aiwebcool.com/ | egrep -i 'x-vercel|server|location|cache|age'
curl -sSI https://aiweb-annygoids-projects.vercel.app/ | egrep -i 'x-vercel|server|location|cache|age'
vercel alias ls --limit 100

The useful details to capture are:

  • failing custom-domain x-vercel-id

  • exact UTC timestamp of the failing request

  • deployment URL/ID that should receive the alias

  • vercel domains verify result

  • the vercel alias ls line showing where aiwebcool.com is assigned

I would not keep removing/re-adding the domain if Vercel already shows Valid Configuration and the direct --resolve test still fails. That can make the timeline harder to reason about. At this point the most actionable ask is for someone to compare the alias/control-plane state with the edge request ID that returned NOT_FOUND.

Hi Ryu,

Thanks for the detailed analysis and guidance. I have stopped making any DNS
flips or domain removal/re-additions to keep the state stable for investigation.

Evidence package captured (2026-07-20T12:15Z):

  1. Failing request x-vercel-id: sin1::v9z7b-1784549708869-14753d9af235
  2. UTC timestamp: 2026-07-20T12:15:09Z
  3. Deployment that should serve: aiweb-6907ffpkk-annygoids-projects.vercel.app (Ready, prod)
  4. vercel domains verify: status=ok, configured_correctly, verified for project aiweb, misconfigured=false
  5. vercel alias ls: aiweb-6907ffpkk-annygoids-projects.vercel.app → aiwebcool.com (age 1d)

curl -sSI https://aiwebcool.com/ returns:
HTTP/1.1 404 Not Found
X-Vercel-Error: NOT_FOUND
X-Vercel-Id: sin1::v9z7b-1784549708869-14753d9af235

Conclusion:
The control plane (alias + verify) correctly points aiwebcool.com at the
production deployment (aiweb-6907ffpkk), but the edge still returns NOT_FOUND.

Could Vercel support compare the alias/control-plane state against edge request
id sin1::v9z7b-1784549708869-14753d9af235 and force-refresh the edge routing
entry for aiwebcool.com?


Appendix: Raw Command Outputs for reference

[1] curl -sSI https://aiwebcool.com/ | egrep -i ‘x-vercel|server|location|cache|age’
HTTP/1.1 404 Not Found
Cache-Control: public, max-age=0, must-revalidate
Server: Vercel
Strict-Transport-Security: max-age=63072000
X-Vercel-Error: NOT_FOUND
X-Vercel-Id: sin1::v9z7b-1784549708869-14753d9af235

[2] curl -sSI https://aiweb-6907ffpkk-annygoids-projects.vercel.app/ | egrep -i ‘x-vercel|server|location|cache|age’
(Live headers not captured from my location: *.vercel.app is SNI-filtered here -
TLS connection is reset on every attempt across multiple edge IPs (76.76.21.21,
76.76.21.93, 76.76.21.41). The deployment is confirmed serving 200 from external
nodes via check-host.net on 2026-07-19. Happy to capture its x-vercel-id from a
VPN node if useful.)

[3] vercel domains verify aiwebcool.com
status: ok
reason: configured_correctly
message: aiwebcool.com has a valid configuration and is verified for project aiweb
domainStatus: configured-correctly
misconfigured: false

[4] vercel alias ls --limit 100
aiweb-6907ffpkk-annygoids-projects.vercel.app aiwebcool.com 1d

Hi Annygoid,

Thanks for capturing that. I think this is now a pretty clean escalation package.

The important combination is:

vercel domains verify -> configured correctly / verified
vercel alias ls -> aiwebcool.com assigned to aiweb-6907ffpkk...
https://aiwebcool.com -> Vercel response, but X-Vercel-Error: NOT_FOUND

That rules out a lot of the normal domain checks, because the request is reaching Vercel and the control-plane commands say the alias/domain assignment exists.

I’d keep the DNS/domain state exactly as-is now and avoid removing/re-adding the domain again. The most useful next step is probably for Vercel support to compare this request ID with the alias state:

X-Vercel-Id: sin1::v9z7b-1784549708869-14753d9af235
Timestamp: 2026-07-20T12:15:09Z
Domain: aiwebcool.com
Expected deployment: aiweb-6907ffpkk-annygoids-projects.vercel.app

One extra control that might help, only if you can run it from a VPN or external shell, is to capture the same two requests from the same location:

curl -sSI https://aiwebcool.com/
curl -sSI https://aiweb-6907ffpkk-annygoids-projects.vercel.app/

If the deployment URL returns 200 from that location while the custom domain still returns X-Vercel-Error: NOT_FOUND, that makes the edge-alias mismatch even clearer.