LeakPatrol › Guides

Supabase error 42501 "permission denied for table": the safe fix

By LeakPatrol · Updated 4 November 2026

If your Lovable, Bolt or Cursor app suddenly says permission denied for table (Postgres error 42501) on a new table, it's not a bug and it's not Row Level Security. Since 30 October 2026, Supabase no longer grants new tables to the Data API automatically. The fix is one GRANT, but the fix AI tools usually suggest can open your whole table to anyone.

Why it happens

Your app talks to Supabase through the Data API (supabase-js) as one of two roles: anon for logged-out visitors and authenticated for signed-in users. A role needs a Postgres GRANT before it can touch a table at all. Tables created before 30 October got those grants automatically. New ones don't, so the first request fails with 42501.

A quick way to tell the two errors apart (both use code 42501): "permission denied for table" means a missing grant. An empty result or "new row violates row-level security policy" means RLS is blocking you, which is usually correct (see the RLS error guide).

The safe fix

Turn RLS on and add a policy first, then grant only what the app needs, only to the role that needs it. For a table of each user's own rows:

alter table public.notes enable row level security;

create policy "Users manage their own notes"
on public.notes for all
to authenticated
using (auth.uid() = user_id)
with check (auth.uid() = user_id);

grant select, insert, update, delete on public.notes to authenticated;

For a table everyone may read but nobody may change from the browser, like a list of products or blog posts:

alter table public.products enable row level security;

create policy "Anyone can read products"
on public.products for select
using (true);

grant select on public.products to anon, authenticated;

The fixes that leave your data open

When you paste 42501 into an AI tool, watch for these. Each one makes the error go away and the table readable or writable by anyone who has your anon key, which is in your app's JavaScript.

A prompt to paste into Lovable, Bolt or Cursor

My Supabase table is giving error 42501 "permission denied for table".
Fix it safely:
1. Enable Row Level Security on the table first, with policies so users
   only read and change their own rows (auth.uid() = user_id), including
   WITH CHECK on insert and update.
2. Then grant only the needed privileges (select, insert, update, delete),
   only to the authenticated role. Do not grant to anon unless the data is
   meant to be public, and never use GRANT ALL.
3. Do not disable RLS, do not use using (true) on user data, and do not
   use the service_role key in the frontend.
Show me the SQL before running it.

Check the tables you already have

The 30 October change only affects new tables. Older ones keep their grants, so a table that was open before is still open. These two queries show where to look:

select tablename, rowsecurity from pg_tables where schemaname = 'public';

select table_name, string_agg(privilege_type, ', ') as privileges
from information_schema.role_table_grants
where grantee = 'anon' and table_schema = 'public'
group by table_name;

Any table with RLS off that anon can select from is readable by anyone. LeakPatrol's free scan checks your live app from the outside for leaked keys and public files in about a minute, and our RLS policy generator writes the grants and policies for common table types.

Check your app in a minute

Free, read-only, no sign-up. Every problem comes with a plain-English fix and a prompt for your AI tool.

Get the 10-point checklist

Every check we run on AI-built apps, with how to do each one yourself. Straight to your inbox.

Questions

What does Supabase error 42501 permission denied for table mean?

The role your app uses (anon or authenticated) has no Postgres GRANT on that table. Since 30 October 2026, new tables in the public schema are not granted to the Data API automatically, so the first request to a new table fails with 42501.

How do I fix 42501 in Supabase safely?

Enable Row Level Security and add policies first, then grant only the privileges your app needs, usually select, insert, update and delete, to the authenticated role. Grant to anon only for data meant to be public, and never use GRANT ALL.

Is GRANT ALL to anon safe in Supabase?

No. It gives logged-out visitors every privilege on the table, including insert, update, delete and TRUNCATE, which Row Level Security does not cover. One missing or loose policy and anyone with your public anon key can change your data. Grant only the specific privileges you need.

Is 42501 the same as an RLS error?

Both use code 42501, but the message differs. "permission denied for table" means a missing grant. A Row Level Security block usually returns no rows on select, or "new row violates row-level security policy" on insert or update.

More guides