Supabase breaking changes, updated weekly

Every verified Supabase trap in Footgun: changes and behaviors that break code or give wrong results, newest first. Each one has the error you see, the fix, and the date it was last checked. The list updates when the weekly check adds or retires a trap. For the full cause and sources, open the trap, or see all Supabase traps.

  1. fg-0570· added 2026-10-27· last checked 2026-10-27

    Anyone with your Supabase publishable or anon key can read and write a table that has RLS off

    Symptom

    Rows can be read through the Data API with only the project URL and the publishable or anon key, no sign-in

    Fix

    Enable RLS on every table in an exposed schema, then add policies for exactly the access each role needs. Once RLS is on, the publishable key reaches no rows until a policy allows it, so write the policies before your app relies on the table.

  2. fg-0571· added 2026-10-27· last checked 2026-10-27

    Files in a public Supabase Storage bucket can be downloaded by anyone who has the URL

    Symptom

    A file URL opens in a private browser window with no sign-in

    Fix

    Keep private user files in a private bucket and serve them with short-lived signed URLs created on the server, or with an authenticated request that carries the user's token. Use public buckets only for files anyone may see, such as avatars or marketing images.

  3. fg-0569· added 2026-10-27· last checked 2026-10-27· deadline 2026-12-31

    A Supabase service_role or secret key in browser code lets anyone skip every RLS policy

    Symptom

    The service_role key or an sb_secret_ key is set in a NEXT_PUBLIC_ variable or passed to createClient in a client component

    Fix

    Use only the publishable key (or the legacy anon key) in browser and mobile code, and keep secret keys in server-only environment variables without the NEXT_PUBLIC_ prefix. If a secret key was ever shipped or committed, fix the cause of the leak first, then create a new secret key, replace it everywhere, confirm every component uses it, and delete the old one.

  4. fg-0196· added 2026-10-15· last checked 2026-10-15

    prepared statement already exists errors when connecting to Supabase through the pooler on port 6543

    Symptom

    prepared statement "s0" already exists

    Fix

    Turn off prepared statements in the driver when using port 6543, or use session mode or a direct connection for code that needs them, including migrations.

  5. fg-0203· added 2026-10-15· last checked 2026-10-15

    Supabase Realtime postgres_changes subscription says SUBSCRIBED but never receives any events

    Symptom

    Channel status SUBSCRIBED, then silence when rows change

    Fix

    Add the table to the publication, confirm the subscriber can select the changed row, and set replica identity full if you need old values on tables without RLS.

  6. fg-0205· added 2026-10-15· last checked 2026-10-15

    Supabase signUp fails with Database error saving new user after adding a profiles trigger

    Symptom

    AuthApiError: Database error saving new user (500, unexpected_failure)

    Fix

    Declare the function security definer with search_path set to empty, fully qualify every table, make inserted columns nullable or defaulted, and read the real error in the Auth and Postgres logs.

  7. fg-0206· added 2026-10-15· last checked 2026-10-15

    Supabase Storage upload fails with 403 new row violates row-level security policy despite an INSERT policy

    Symptom

    StorageApiError: new row violates row-level security policy (403)

    Fix

    Add SELECT (and UPDATE if you overwrite) policies on storage.objects that mirror the INSERT policy's bucket and path checks.

  8. fg-0202· added 2026-10-15· last checked 2026-10-15

    Supabase queries hang forever after awaiting a Supabase call inside onAuthStateChange

    Symptom

    The next supabase.from(...) or getSession() anywhere in the app never resolves, with no error

    Fix

    Upgrade to supabase-js 2.107.0 or later. On older versions keep the callback synchronous and defer any Supabase call with setTimeout. Even on new versions, never call refreshSession from a TOKEN_REFRESHED handler.

  9. fg-0199· added 2026-10-15· last checked 2026-10-15

    Supabase client created with the service role key still gets RLS errors or empty results

    Symptom

    new row violates row-level security policy from a client built with the service_role or sb_secret key

    Fix

    Build a separate admin client with plain createClient, no cookies, and session persistence off. Create users with auth.admin.createUser rather than signUp on that client.

  10. fg-0195· added 2026-10-15· last checked 2026-10-15

    Connecting to the Supabase database from Vercel or GitHub Actions fails with ENETUNREACH

    Symptom

    connect ENETUNREACH 2a05:... :5432

    Fix

    Use the pooler connection string (transaction mode on port 6543 for serverless, session mode on 5432 for long-lived servers), or buy the dedicated IPv4 add-on on Pro and above.

  11. fg-0197· added 2026-10-15· last checked 2026-10-15

    Server logs fill with Using the user object as returned from supabase.auth.getSession() could be insecure

    Symptom

    Using the user object as returned from supabase.auth.getSession() or from some supabase.auth.onAuthStateChange() events could be insecure

    Fix

    Use getClaims() to verify the JWT, or getUser() to ask the Auth server, whenever an identity decision is made on the server. Read only the access token from getSession, never the user object.

  12. fg-0198· added 2026-10-15· last checked 2026-10-15

    Supabase Auth confirmation and magic link emails fail with Email address not authorized or hit a rate limit

    Symptom

    Email address not authorized when signing up anyone outside the project team

    Fix

    Configure a custom SMTP provider before launch, then raise the email rate limit on the Auth rate limits page to match expected signups.

  13. fg-0253· added 2026-10-15· last checked 2026-10-15

    Supabase Edge Function returns 401 Invalid JWT for signed-in users after switching to asymmetric JWT signing keys

    Symptom

    {"code":401,"message":"Invalid JWT"} when the client sends a logged-in user's access token

    Fix

    Turn off verify_jwt for the function and authenticate inside the handler, for example with getClaims on a client built from the request's Authorization header, or with the @supabase/server SDK.

  14. fg-0201· added 2026-10-15· last checked 2026-10-15

    Supabase OAuth or magic link ignores redirectTo and sends users to localhost or the Site URL

    Symptom

    After Google sign-in the browser lands on http://localhost:3000 in production

    Fix

    Add every production, preview, and local callback URL to the allow list, using wildcards for preview domains, and set Site URL to production.

  15. fg-0204· added 2026-10-15· last checked 2026-10-15

    Supabase select returns an empty array with no error even though the table has rows

    Symptom

    { data: [], error: null } for a table that has data in the Table Editor

    Fix

    Add a SELECT policy for the role that actually makes the call, and confirm a user JWT is attached at call time by checking auth.jwt() through an RPC.

  16. fg-0207· added 2026-10-15· last checked 2026-10-15

    Supabase update returns no error but changes nothing because the table has no SELECT policy

    Symptom

    update() resolves with error null and status 204 while the row is unchanged

    Fix

    Add a SELECT policy covering the same rows as the UPDATE policy, and chain .select() in tests so a zero-row update is visible.

Have your agent check Supabase changes before it codes

$ /plugin marketplace add getfootgun/footgun
$ /plugin install footgun@footgun