Get help

Check your Supabase migrations for missing GRANTs

Paste a migration (or a few). This finds new public tables that will hit 42501 permission denied after October 30, 2026, and writes the GRANT statements for you.

Your SQL never leaves your browser.

By default the fix grants authenticated and service_role only. A grant only counts as done when every role has the privileges it needs. Pasting several tables? The boxes above are the default for all of them. After a check, each table in the results has its own boxes if you need different access.

Comments and string literals are ignored. Tables in auth, storage, or other schemas are skipped.

What changes on October 30

On October 30, 2026, existing Supabase projects stop auto-granting privileges on new tables in the public schema. Until now, a CREATE TABLE in public quietly received SELECT, INSERT, UPDATE, and DELETE for anon, authenticated, and service_role. After the change, the table is there, your RLS policies can look fine, and the Data API still cannot see it.

The failure is Postgres error 42501, permission denied for table. PostgREST (the layer behind supabase-js) returns that code with a hint that names the missing GRANT. The app often surfaces it as a 401 or 403. This is not an RLS miss. Postgres checks grants first. If the role has no privilege on the table, policies never run.

Only new tables in the public schema created without GRANTs fail. Existing tables keep their current grants and stay reachable. New projects already dropped the old default (rollout from May 30, 2026). October 30 applies the same rule to every existing project.

Source: Supabase changelog (April 28, 2026) and the Securing your API docs. Same facts as our Oct 30 GRANT guide.

Who it affects

You are in scope if a Lovable app, or any other supabase-js client, creates tables in public and talks to them through the Data API (REST, GraphQL, or the client libraries). A typical Lovable migration does CREATE TABLE, ENABLE ROW LEVEL SECURITY, and CREATE POLICY, then stops. After October 30 that file ships a table nobody can reach from the app.

You are not in scope if you only use a direct Postgres connection (psql, an ORM, a connection string). storage, auth, realtime, and custom schemas keep their current defaults. Existing tables are not rewritten. The change is a default for future public tables, not a revoke on what you already have.

How to fix it by hand

Put the GRANT in the same migration as the table, RLS, and policies. Least privilege, not GRANT ALL on the whole schema. The usual app table looks like this:

alter table public.your_table enable row level security;

-- signed-in users: the operations your app actually uses
grant select, insert, update, delete on table public.your_table to authenticated;

-- server code / Edge Functions using the service_role key
grant select, insert, update, delete on table public.your_table to service_role;

-- only if signed-out visitors should read this table
-- grant select on table public.your_table to anon;

Leave anon with nothing unless signed-out visitors should read that table. A public posts table might get SELECT to anon. A profiles or invoices table should not. This checker leaves anon out by default. Tick the signed-out visitors box only for tables like that public posts table, and it adds SELECT for anon. If your app never deletes rows as a signed-in user, trim DELETE from the authenticated line too.

If you already see 42501, add a follow-up migration (or paste the GRANT into the SQL editor). Do not drop and recreate the table. Then retry the request. Skip GRANT ALL ON ALL TABLES IN SCHEMA public unless you really want every table opened, including ones with no RLS.

This page never uploads your SQL. There is no form post, no API call, and no analytics event with the paste. Check the file locally, copy the missing statements, and keep the rest of the migration as you wrote it.

FAQ

Does the October 30 change break my existing Supabase tables?

No. Existing tables keep their current grants and stay reachable. The change only affects new tables you create in the public schema after it reaches your project: they need an explicit GRANT before the Data API can see them.

Does this affect tables in the storage, auth, realtime or custom schemas?

No. Supabase says the change touches default privileges in the public schema only. Tables in storage, auth, realtime and custom schemas keep their current grants and defaults.

Will I be affected if I use a direct Postgres connection?

No. If your app only reads and writes Postgres over a direct connection (psql, an ORM, or an app server with a connection string), the change does not affect you. It applies to the Data API that supabase-js and the other client libraries call.

Is a missing GRANT the same as a missing RLS policy?

No. Grants control whether a role can access a table at all; RLS controls which rows that role can see. If the grant is missing, Postgres rejects the query with error 42501 before RLS comes into play, and the PostgREST hint names the GRANT to add.

Can I switch to the new behavior before October 30?

Yes. Supabase documents running alter default privileges ... revoke statements for the postgres role in the public schema from the SQL Editor. Existing objects keep their grants; new tables then need explicit GRANT statements. The same changelog shows how to roll back.

Answers from the Supabase changelog: tables not exposed to the Data API automatically (rollout timeline, FAQ and opt-in sections), checked October 26, 2026.