Setup:
Azure Static Web App, Standard plan, West Europe.
- publicNetworkAccess = Disabled. The app is reachable only via a Private Endpoint inside a VNet. Inbound user traffic enters through Zscaler ZPA App Connectors in that VNet.
- PII
- Custom domain: project.contoso.software (status Validated/Ready; public DNS at an external registrar resolves, certificate auto-renewal is healthy).
- Private DNS zones in the VNet: privatelink.7.azurestaticapps.net (resolves the autogenerated host to the PE IP) and a zone for the custom domain (CNAME custom -> autogenerated host).
- az staticwebapp environment list returns exactly one environment: default, status Ready. No staging/preview environments.
Problem:
Existing static assets intermittently return the Static Web Apps branded "404: Not Found" page when requested on the custom domain, while the autogenerated hostname served them stably (before I set the custom domain as the default domain, which now makes the autogenerated host return a 301 redirect).
Evidence (the part I can't explain) 50 sequential requests for one existing asset, forcing the connection to the single production private-endpoint IP (so DNS/round-robin is out of the picture), run on the in-VNet ZPA connector (no browser/proxy/CDN cache):
curl -skv --resolve project.contoso.software:443:10.20.0.5 -w "%{http_code} %{content_type} %{size_download}\n" https://project.contoso.software/assets/index-DRkdI0yH.js
Result: 38x 200 / 12x 404 (about 24%), binary outcome, never partial:
- 200 -> text/javascript, full file (about 198 KB)
- 404 -> text/html, about 2.4 KB, the SWA branded "We couldn't find that page"
The TLS certificate is identical on the 200 and the 404 responses (same custom-domain certificate, same SHA-256 fingerprint), confirmed in the browser certificate viewer. So the failing requests do reach a backend that holds the custom-domain certificate, but that backend returns the branded 404 for every path including /index.html, i.e. it behaves like a content slot with no deployed site.
What I've ruled out
- Build / missing file: the same asset returns the full correct file 76% of the time; the 200 body is always complete.
- staticwebapp.config.json / navigationFallback: a fallback would return index.html with HTTP 200; I get HTTP 404 plus the platform branded page.
- TLS / custom-domain binding / certificate: identical custom certificate on both 200 and 404.
- DNS / wrong (staging) IP: the connection is pinned to one IP and still flaps about 24%, so the inconsistency is behind that single PE IP.
- Zscaler ZPA: reproduced directly on the connector against the raw PE IP; ZPA does not rewrite the Host header.
- Stray environment: only the single default environment exists.
- SWA "Availability and Performance" shows Site Errors = 0.
Question Behind a single private-endpoint IP, with only one default environment and a correctly served custom-domain certificate, why is the custom Host intermittently served by an empty content slot (branded 404), while the autogenerated hostname is stable? Is this a known behavior of the Static Web Apps content backend / scale-unit replicas behind a private endpoint, and how do I force the custom Host to consistently hit the populated production content? Any pointers before I escalate via a support case would be appreciated.