Troubleshooting: CORS
Symptoms
Section titled “Symptoms”- Browser error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. - Browser error:
Response to preflight request doesn't pass access control check. - Requests fail only in production, while local development works.
Common causes
Section titled “Common causes”- Backend CORS allowlist does not match frontend origin exactly.
- Wrong Koyeb public path (for example, service mounted under
/api/v1/healthinstead of/). - Frontend points to an outdated backend URL.
- Backend env vars changed but service was not redeployed.
- Preflight
OPTIONSrequest is not reaching the expected backend service.
Diagnostic steps
Section titled “Diagnostic steps”- Confirm backend health and base URL:
GET https://api.korta.click/api/v1/health - Run preflight test manually:
curl -i -X OPTIONS 'https://api.korta.click/api/v1/urls/public' \ -H 'Origin: https://korta.click' \ -H 'Access-Control-Request-Method: POST' \ -H 'Access-Control-Request-Headers: content-type'- Check Koyeb env vars:
NODE_ENV=productionFRONTEND_URL=https://korta.clickCORS_ORIGINS=https://korta.click - Check Koyeb routing:
Public path must be /Health check path should be /api/v1/health - Verify frontend env:
VITE_API_URL=https://api.korta.click/api/v1
- Set exact frontend origin in backend env (no wrong domain, no stale URL):
CORS_ORIGINS=https://korta.click - Keep Koyeb public route at
/(do not use/api/v1/healthas public route). - Redeploy backend after every env change.
- If using additional frontend domains, add all of them to
CORS_ORIGINS(comma-separated).
Verification
Section titled “Verification”- Preflight
OPTIONSreturns CORS headers (Access-Control-Allow-Origin). - Anonymous shorten endpoint works from landing page without browser CORS errors.
- OAuth flow and authenticated requests work from the production frontend domain.