cors error

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

Next.js Route Handler — OPTIONS responder
// 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.