VibeCPR

← All fixes

Supabase · Edge Functions

Fix Supabase Edge Function "blocked by CORS policy" (preflight)

Updated · Applies to: Supabase, Lovable, Bolt, Cursor, v0

TL;DR fix: The browser sends an OPTIONS preflight before your real request, and your function doesn't answer it with CORS headers. Often it crashes first trying to req.json() an empty body. At the very top of the function, return early for OPTIONS with corsHeaders, and include corsHeaders on every success and error response. Then redeploy the function.

Steps

  1. Confirm it's CORS, not your logic. If the same call works from curl or Postman but fails in the browser with 'Response to preflight request doesn't pass access control check', the OPTIONS preflight is the problem. curl doesn't do CORS; browsers do.
  2. Handle OPTIONS before anything else. The OPTIONS check must come before req.json() or any auth or business logic. A preflight has no body, so parsing it throws and the response has no CORS headers.
  3. Use Supabase's corsHeaders. Import corsHeaders from the Supabase JS SDK (v2.95.0 and later) so the allowed headers match what supabase-js sends, or define them in a shared cors.ts on older versions.
  4. Add CORS headers to error responses too. A 400 or 500 without CORS headers shows up in the browser as a CORS error and hides the real error message.
  5. Redeploy the function. Run supabase functions deploy <name> (or redeploy from your builder). Edits to local files don't apply until you deploy.

The function skeleton

import { corsHeaders } from "npm:@supabase/supabase-js@^2/cors";

Deno.serve(async (req) => {
  // 1. Answer the browser's preflight FIRST, before reading the body
  if (req.method === "OPTIONS") {
    return new Response("ok", { headers: corsHeaders });
  }

  try {
    const { name } = await req.json();
    return Response.json({ message: `Hello ${name}!` }, { headers: corsHeaders });
  } catch (error) {
    // 2. Errors need CORS headers too, or the browser hides them as "CORS errors"
    const message = error instanceof Error ? error.message : String(error);
    return Response.json({ error: message }, { status: 400, headers: corsHeaders });
  }
});

On @supabase/supabase-js older than v2.95.0, Supabase’s docs say to hardcode the headers in supabase/functions/_shared/cors.ts:

export const corsHeaders = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Headers":
    "authorization, x-client-info, apikey, content-type, x-retry-count, traceparent, tracestate, baggage",
  "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
};

Prompt for your AI tool

Browser calls to our Supabase Edge Function fail with "Response to preflight request doesn't pass access
control check". In the function: return early for OPTIONS with corsHeaders BEFORE req.json(), add corsHeaders
to every success and error response, keep the auth check. Then tell me the deploy command.

When to get help

Get help if the function also handles payments, webhooks or secrets, if you need to lock Access-Control-Allow-Origin to your own domain, or if errors persist after redeploying (often an auth/JWT problem hiding behind the CORS message).

FAQ

Why does my Supabase Edge Function work in Postman but fail in the browser with a CORS error?

Browsers send an OPTIONS preflight request before cross-origin calls with headers like Authorization and apikey. Postman and curl don't. If your function doesn't return CORS headers for OPTIONS, the browser blocks the real request. Return early for OPTIONS with corsHeaders at the top of the function.

Can I fix it by setting mode: 'no-cors' in fetch?

No. no-cors gives you an opaque response your code can't read, and supabase.functions.invoke won't work with it. Fix the headers on the function side.

Is Access-Control-Allow-Origin: * safe?

For functions that use the user's JWT for authorization it is common and matches Supabase's examples. CORS is not access control. Your function must still check who the user is. You can restrict the origin to your domain for defense in depth.

Sources

Related fixes