Security · Supabase

Supabase's October 30 grants change: what breaks, and the prompt that fixes it

Short answer

  • On October 30, 2026, Supabase stops exposing new tables in the public schema to the Data API automatically, on all existing hosted projects.
  • After that, a new table without an explicit GRANT fails from supabase-js with error 42501, "permission denied for table". Existing tables keep their grants.
  • If an AI tool (Lovable, Bolt, Replit Agent) creates your tables, add grant + RLS + policies to its instructions now. And note: tables that are already open without RLS stay open.

On October 30, 2026, Supabase applies a breaking change to every existing hosted project: tables you create in the public schema are no longer exposed to the Data API automatically. If you build with Lovable, Bolt, Replit Agent or any AI tool on top of Supabase, this matters to you, because those tools create tables for you. This guide explains what changes, what breaks, the three-step fix, and a prompt you can paste into your AI tool today. Source: the official Supabase changelog.

What changes on October 30

Until now, a default Supabase project granted select, insert, update and delete on every table in public to the anon, authenticated and service_role roles. Create a table, and it was instantly reachable through the Data API: PostgREST, GraphQL, supabase-js and the other client libraries.

After the change reaches your project, new tables in public require an explicit Postgres GRANT before the Data API can see them. In Supabase's words: "Existing tables are not affected in your project, they keep their current grants and stay reachable."

  • May 30, 2026: already the default for new projects (gradual rollout).
  • October 30, 2026: enforced on all existing projects.
  • Supabase emails owners and admins: a five-week notice on September 23 and a final notice on October 23.
  • Not affected: self-hosted Supabase, and apps that only use a direct Postgres connection (psql, an ORM or a server with a connection string). Tables in storage, auth, realtime and custom schemas keep their current defaults.

Row Level Security does not change. Grants are a separate layer: the grant decides whether a role can touch a table at all, RLS decides which rows it sees.

What breaks: error 42501

If a grant is missing, PostgREST returns this instead of data:

{
  "code": "42501",
  "message": "permission denied for table your_table",
  "hint": "Grant the required privileges to the current role with: GRANT SELECT ON public.your_table TO anon;"
}

For an AI-built app, the realistic scenario is this: after October 30 you ask your AI tool for a new feature (comments, invoices, a waitlist). It creates a new table, writes the frontend code, and the feature fails with 42501 because nobody granted access. Your existing features keep working. The new one does not, until the grants are added.

The trap: an AI tool that sees "permission denied" may try to "fix" it by disabling RLS or loosening policies. That is the wrong fix. RLS is not the problem; the missing grant is.

The fix: grant, RLS, policies, as one unit

Supabase recommends treating these three steps as a unit whenever you create a table you want to reach from the Data API. This is the SQL from the changelog, with your_table to replace:

-- 1. Grant the privileges the role needs
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;
grant select, insert, update, delete on public.your_table to service_role;

-- 2. Enable RLS
alter table public.your_table enable row level security;

-- 3. Add the policies you need
create policy "users can read their own rows"
  on public.your_table
  for select
  to authenticated
  using (auth.uid() = user_id);

Only grant what each role needs. Most tables should not be readable by anon (logged-out visitors) at all: drop that first line unless the data is meant to be public.

Copy-paste prompt for Lovable, Bolt or Replit Agent

Supabase recommends updating the system prompt of your AI coding tool, or adopting the Supabase agent skill. If your tool has project-level instructions or knowledge (Replit Agent reads replit.md), add this:

Supabase rule for this project: whenever you create a table in the
public schema, do these three things in the same migration:
1. GRANT only the privileges each role needs. authenticated: the
   actions logged-in users need. service_role: select, insert,
   update, delete. anon: nothing, unless the data is public, then
   select only.
2. ALTER TABLE ... ENABLE ROW LEVEL SECURITY.
3. CREATE POLICY rules so users only read and change their own rows
   (for example auth.uid() = user_id).
If you see error 42501 "permission denied for table", add the missing
GRANT from the error hint. Never disable RLS or add a policy that
allows everyone to fix it.

Quick self-check (2 minutes)

Run this in the Supabase SQL Editor. It lists every table in public, whether RLS is on, and whether the anon and authenticated roles can read it:

select c.relname as table_name,
       c.relrowsecurity as rls_enabled,
       has_table_privilege('anon', c.oid, 'select') as anon_can_select,
       has_table_privilege('authenticated', c.oid, 'select') as authenticated_can_select
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public' and c.relkind = 'r'
order by rls_enabled, table_name;
  • rls_enabled = false and anon_can_select = true: fix this first. Anyone with your anon key, which ships in your frontend, can read that table.
  • rls_enabled = true: check that your policies only return the rows each user should see.
  • The Security Advisor and the Data API exposure badge in the Table Editor also flag tables worth reviewing.

Want to test the new behavior before October 30? The changelog gives the statements to opt in early on an existing project, and a rollback. Try it on a test or staging project first.

The twist: October 30 does not close what is already open

It is tempting to read this change as "Supabase is locking things down, so I'm covered". You are not. The change only applies to new tables. Every existing table keeps the grants it has today, including tables that are readable with the public anon key and have RLS turned off. Those stay exactly as open after October 30 as they are now.

If you want to tighten an existing table you never meant to expose, Supabase gives the statement: revoke all on table public.your_table from anon, authenticated, service_role;. Make sure your app does not read it through the Data API first.

Before October 30: short checklist

  1. Add the prompt above to your AI tool's project instructions.
  2. Run the self-check query and fix any table with RLS off that anon can read.
  3. Make sure any migration or provisioning script that creates tables in public includes the GRANT statements.
  4. After October 30, if a new feature fails with 42501, add the grant from the error hint. Do not disable RLS.

Simo · Snapforge Lab

FAQ

Will my Supabase app break on October 30, 2026?

Not by itself. Existing tables keep their current grants and stay reachable. What fails is the next new table created in the public schema without an explicit GRANT: requests to it from supabase-js return error 42501 until the grant is added.

What does error 42501 "permission denied for table" mean in Supabase?

The role making the request (anon or authenticated) has no privilege on that table. Postgres rejects the query before Row Level Security is even checked. The error hint contains the exact GRANT statement to run.

Should I fix 42501 by disabling RLS?

No. RLS is not the cause. Add the missing GRANT for the role in the error hint, keep RLS enabled, and make sure a policy allows the rows that role should see.

Does the October 30 change make my existing tables safer?

No. Existing tables keep the grants they already have. A table that is readable with your public anon key and has RLS turned off stays that way after October 30. Check it with the query in this guide.

Am I affected if I self-host Supabase or use a direct Postgres connection?

No. Supabase lists self-hosted as not affected, and apps that only talk to Postgres over a direct connection (psql, an ORM or a server with a connection string) are not affected either.

Get a free audit