Supabase error 42501 "permission denied for table": the safe fix
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.
grant all on public.my_table to anon: gives logged-out visitors every privilege, including insert, update and delete, plusTRUNCATE, which RLS doesn't cover at all. If a policy is missing or too loose, anyone can change your data. Grant only the specific privileges you need.- Granting to
anonon a table of user data. Logged-out visitors never need to read your users' rows. - Granting before RLS is on. Between the grant and the policy, every row is public. If the AI forgets the policy, it stays that way.
disable row level securityor ausing (true)policy on user data, to make "the error" go away.- Putting the service_role key in the frontend to bypass permissions. That key skips RLS completely.
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.
Plus an email when automatic re-checks launch, and the odd tip. Unsubscribe any time.
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
- Supabase RLS policy generator (free)
- Is this API key safe in my frontend? Free key checker
- Security scan MCP server for Claude Code, Cursor and other AI agents
- Supabase's October 30 change: what it fixes for your app's security, and what it doesn't
- Supabase "new row violates row-level security policy": 5 causes and the safe fix
- Supabase service_role key exposed? What to do in the next hour
- Lovable security check: is your Lovable app safe?
- Bolt.new security check: is your Bolt app safe?
- Launch checklist for apps built with Lovable, Bolt and Cursor
- Supabase security check: is your anon key safe? (RLS checker)
- How to check if your API key is exposed on your website
- Are VITE_ env variables secret? How to hide API keys
- Stop users giving themselves your paid plan (Supabase)