CORS preflight: Response did not pass access control check
The error
Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
What it means
For "non-simple" cross-origin requests (anything with custom headers or non-GET/POST), the browser sends an OPTIONS preflight first. Your server returned a non-2xx status or missing CORS headers.
Many backends route OPTIONS to a 404 handler because they only define GET/POST. The preflight fails, and the actual request never fires. The fix is either explicit OPTIONS handlers or middleware that responds to all OPTIONS.
The fix
// app/api/data/route.ts
const ALLOWED_ORIGIN = 'https://yoursite.com';
const corsHeaders = {
'Access-Control-Allow-Origin': ALLOWED_ORIGIN,
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
};
export async function OPTIONS() {
return new Response(null, { status: 204, headers: corsHeaders });
}
export async function POST(req: Request) {
// ... your handler
return new Response(JSON.stringify({ ok: true }), {
headers: { 'Content-Type': 'application/json', ...corsHeaders },
});
}Also check
Common adjacent root causes when the obvious fix doesn’t work.
- 01Behind a reverse proxy? The proxy may swallow OPTIONS — explicitly forward them.
- 02Using a custom Authorization header? It triggers preflight. Make sure 'Authorization' is in Access-Control-Allow-Headers.
- 03Setting Access-Control-Allow-Credentials: true? Then Allow-Origin must NOT be "*". Echo a specific origin from an allowlist.
Scan for related issues
This error is in our cors scanner. Run a free scan to find what else is misconfigured in the same area.
FAQ
Frequently asked questions
- Why does the browser preflight at all?
- Preflights protect non-CORS-aware servers. If your endpoint can’t handle a cross-site DELETE, the browser checks first via OPTIONS rather than firing a destructive request blindly.
- Can I disable preflights?
- Only by making the request "simple" — limited methods (GET/POST), limited content types (form, plain text), no custom headers. Most modern apps need custom headers (Auth tokens), so preflights stay.
Related fixes
Tighten this area further
CORS allows all origins
An Access-Control-Allow-Origin: * policy lets any site call your API. Sometimes that is fine, often it is a mistake. Here is how to decide and fix it.
Read moreCORS credentials misconfiguration
Setting both Allow-Origin: * and Allow-Credentials: true is a dangerous misconfiguration. Here is why browsers block it and how to fix it correctly.
Read more