CORS preflight / OPTIONS request failed
If the browser blocks a cross-origin request during preflight, the problem is usually in the OPTIONS response that is supposed to approve the real request before it is sent.
What this error means
Some cross-origin requests require a preflight before the browser sends the real request. The browser sends an OPTIONS request describing the method and headers it wants to use.
If that preflight does not succeed, or its CORS headers do not approve the requested origin, method, and headers, the browser blocks the real request.
Check these first
- Open DevTools → Network and find the
OPTIONSrequest immediately before the failure. - Confirm the preflight receives a successful response instead of an auth error, server error, timeout, or failed network request.
- Check
Access-Control-Allow-Originand make sure it permits the page origin. - Check
Access-Control-Allow-Methodsand make sure it includes the method the browser wants to send. - Check
Access-Control-Allow-Headersand make sure it permits the non-safelisted request headers listed byAccess-Control-Request-Headers. - Make sure middleware, authentication, a reverse proxy, or a CDN is not rejecting
OPTIONSbefore your CORS handler runs.
See a failing preflight on a real second origin
This request intentionally triggers a preflight and tells AnotherExample’s CORS lab to reject that preflight with HTTP 403. The browser should stop before sending the real PUT request.
fetch('https://cors.anotherexample.com/api/cors/lab?preflightStatus=403&allowOrigin=*&methods=PUT,OPTIONS&headers=Content-Type', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ test: true })
})
.then(r => r.json())
.then(console.log)
.catch(console.error);
Change preflightStatus=403 to preflightStatus=204 and run the same request again. The controlled preflight should succeed, allowing you to compare the two cases without changing the rest of the request.
Common server-side causes
Typical causes include an OPTIONS route that is not handled, authentication running before CORS middleware, a requested method missing from Access-Control-Allow-Methods, a requested header missing from Access-Control-Allow-Headers, or a proxy/CDN returning a different response than your application.
Do not try to solve a preflight failure with mode: 'no-cors'. That produces an opaque response that normal JavaScript cannot inspect, so it is not a substitute for a correct CORS response.
Still stuck?
Compare the request in the CORS Debugger →
Paste the browser error into the Error Explainer →
Explore working and broken preflight scenarios in the Playground →