Incident pattern

CORS error in production but not on the preview URL

The app is fine on its platform-issued preview address and broken on the real domain. The console shows a blocked cross-origin request, the network tab shows a failed preflight, and pages that need data render empty.

  • Any stack
  • Lovable
  • Bolt
  • Replit
  • Auth & login
  • Forms & leads

Root cause, in plain English

A browser only sends a cross-origin request if the server names that exact origin as allowed. Scheme, host and port all count, so a custom domain is a different origin from the preview address, and the bare domain is different again from the one with a leading subdomain. The API was configured while you were on the preview URL, so the domain you actually launched on was never on the list.

How to fix it

  1. Read the failing request in the network tab and note the exact origin the browser sent. That string, character for character, is what has to be allowed.

  2. Add every origin the app is genuinely served from — the custom domain, the leading-subdomain variant, and any preview address you still use — to the API's allowed origins.

  3. Make sure preflight requests are answered too: the browser sends an OPTIONS request first, and a route that only handles POST fails before your handler ever runs.

  4. If the request sends credentials, allow them explicitly and name the origin; a wildcard is rejected by the browser as soon as credentials are involved.

  5. Redeploy the API rather than only the front end — the allow list lives on the server, so a front-end-only deploy changes nothing.

How Nightlamp detects this automatically

  • Browser journey
  • API canary
  • HTTP status

Only a real browser enforces this, which is why a browser_journey is the check that matters: it loads the page from the production origin and fails when the request is blocked. A plain http_status monitor will call the page healthy, because the document returns 200 and only the data requests inside it are refused. An api_canary confirms the API itself is up and the problem is the origin policy.

Catch this before your customers do

Nightlamp runs these checks continuously against your live app and sends a plain-English diagnosis — not a wall of logs — the moment this pattern shows up.

Frequently asked questions

Why did it work before I connected the custom domain?
Because the preview address was the allowed origin. Connecting a domain changes what the browser sends, and nothing on the server was updated to match. The API's configuration is still exactly as correct as it was — for a URL you no longer use.
Can I allow all origins to make it go away?
It will make the error go away and hand every site on the internet the ability to call your API from a visitor's browser. If the API is genuinely public and unauthenticated that may be acceptable; if it carries credentials, browsers will reject the wildcard anyway.
The API returns 200 when I test it with curl. Is it really CORS?
Yes — command-line tools do not enforce the policy. A request that succeeds from a terminal and fails from the browser on the same URL is close to conclusive evidence that the origin, not the endpoint, is the problem.

Newsletter

Get new incident patterns as we publish them

One email when new failure patterns, fixes, and monitoring recipes for no-code and AI-built apps land. No fluff, unsubscribe any time.

Double opt-in. One-click unsubscribe. No spam, ever.