DEV Community

FixLoop
FixLoop

Posted on Edited on Originally published at fixloop.dev

Supabase Oct 30: why new tables get 42501 (and how to fix grants + RLS)

If you just created a table in Lovable, turned on RLS, wrote policies, and the app still returns permission denied for table, this is the one.

Starting October 30, 2026, existing Supabase projects stop auto-granting privileges on new tables in the public schema. The table is there. The policies are there. The Data API still cannot see it.

Source: Supabase changelog · Securing your API

What it looks like

The request fails with Postgres error 42501. PostgREST (the Data API behind supabase-js) sends something like:

{
 "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;"
}
Enter fullscreen mode Exit fullscreen mode

Typical setup: a Lovable-created table, RLS enabled, policies that should allow the row, and it still fails. Old tables keep working. Only the new one fails.

The hint names the missing grant. It is not a recommendation to copy blindly. Read it, then grant only what that role should have.

Grants vs RLS

Postgres runs two checks, in order:

  1. Grants decide whether a role can touch the table at all (SELECT, INSERT, UPDATE, DELETE).
  2. Row Level Security decides which rows that role can see or change.

If the grant is missing, RLS never runs. That is why "I have policies" does not fix 42501.

Until now, a new table in public automatically received select/insert/update/delete for anon, authenticated, and service_role. RLS was the only gate. New projects already dropped that default. On October 30 it applies to every existing project too.

Existing tables keep their grants. Direct Postgres connections are not affected. This is a Data API change: REST, GraphQL, and the client libraries.

The fix

Put grants in the same migration as the table, RLS, and policies. Least privilege, not GRANT ALL.

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;
Enter fullscreen mode Exit fullscreen mode

Leave anon with nothing unless the table is meant to be public. Skip GRANT ALL ON ALL TABLES IN SCHEMA public - that also opens tables where RLS was never turned on.

If you already see 42501, check who has what:

select grantee, privilege_type
from information_schema.role_table_grants
where table_schema = 'public'
 and table_name = 'your_table';
Enter fullscreen mode Exit fullscreen mode

Tell Lovable to include grants

Paste this into project instructions / Knowledge before the next migration:

When you create or change a Supabase table, put all of this in the same migration: CREATE TABLE, ENABLE ROW LEVEL SECURITY, CREATE POLICY, GRANT to authenticated and service_role, and GRANT SELECT to anon only if signed-out users should read it. Do not use GRANT ALL. Do not skip grants because RLS is on.

Full checklist + FAQ

The longer version with the Lovable paste block, checklist, and FAQ lives here (canonical):

https://fixloop.dev/guides/supabase-oct-30-grants-change


I run FixLoop - we fix broken Lovable/Supabase apps for a fixed price. No fix, no pay.

Top comments (3)

Collapse
 
shipmarkco profile image
Shipmark •

The part builders will miss: existing tables keep their grants, so an app can look fine right up to the day a new table ships. Grant, RLS, and policy as one step in the same migration is the habit that survives this change. A per-table grant beats a schema-wide one every time.

Collapse
 
fixloopdev profile image
FixLoop •

Yep, that's exactly the trap. Old tables keep working, so the first sign is a 42501 on whatever table you ship next. What we've settled on: GRANT right after CREATE TABLE in the same migration, enable RLS and add the policy in that same file, then hit the table once with the anon key before merging. If that request fails, the migration isn't done.

Collapse
 
shipmarkco profile image
Shipmark •

That anon key test is the part most people skip.

A table can look fine in the dashboard.
Then the first real user hits it and gets a 42501.

We run that same check in our launch scan.
If the anon key can read a table it should not, we flag it.
If it cannot read one it should, that fails too.

Grant, RLS, policy, test.
All in the same migration.
That order would save a lot of launches.