Supabase Edge Function CORS error fix: DevTools console shows blocked by CORS policy on the preflight, then corsHeaders on OPTIONS and on errors make functions.invoke work

Supabase Edge Function CORS Error? How to Fix It (2026)

Your Lovable, Bolt, v0 or Cursor app works until it calls a Supabase Edge Function. Then the console fills with red: Access to fetch at ... has been blocked by CORS policy: Response to preflight request doesn't pass access control check, or No 'Access-Control-Allow-Origin' header is present on the requested resource. You searched for the Supabase Edge Function CORS error because the button does nothing and the function logs look fine.

Good news: this is one of the most fixable errors in a vibe-coded app. The browser is asking your function a question before every call (the preflight), and your function is not answering it with the right headers. Sometimes the real problem is a 401, a crash or a missing secret that only looks like CORS. This guide covers all of it, with code you can paste. If the app just moved off the builder, keep our Lovable app broken after export guide open too.

Quick answer: In your Edge Function, return early on OPTIONS with corsHeaders imported from npm:@supabase/supabase-js@^2/cors, and add the same headers to every response, including errors. Read secrets and parse JSON after the preflight check. Redeploy with supabase functions deploy, then call it with supabase.functions.invoke.

What you seeMost likely causeFix
Preflight doesn't pass access control checkNo OPTIONS branch, or it returns non-2xxReturn new Response('ok', { headers: corsHeaders }) first
No 'Access-Control-Allow-Origin' headerSuccess or error response sent without CORS headersSpread corsHeaders into every response, including catch
Request header field x-client-info is not allowedHand-written allow-list missing a header supabase-js sendsImport corsHeaders from the SDK, or add the header
CORS error only when signed out or after a while401 from the verify_jwt check (no or expired JWT)Call with functions.invoke and a live session
CORS error right after you added a secret or importFunction crashes (500 / 503) before headers are setCheck Logs, set the secret, wrap the handler in try/catch
Works on localhost, fails on your domain or Vercel previewCustom origin allow-list misses that originAdd the exact origin, or use the SDK wildcard default
Works in curl, fails only in the browsercurl does not enforce CORSTest the preflight with curl