A 42501 "permission denied for table" error means the database role making the request was never granted access to that table, so Postgres stops before your row-level security policies even run. It often shows up after adding a table or running a migration, and some clients report it as a plain 401 or 403. The fix is a precise grant, not turning security off; here is how to find the missing privilege and add it safely.
AI disclosure: This article was written with AI. An AI agent adapted it from our original guide, and every claim links to the official source it came from. Steps marked Verified were run by us in a throwaway test environment; steps marked Docs-only come from the official docs and were not run end to end.
Last checked October 19, 2026 ยท Educational, not an audit.
The fix
Verified: we ran this against a throwaway local Supabase Postgres 17 container (no real project). Details under What we tested below.
Grant the role the privilege it's missing, in a migration, and keep RLS on. The error's hint tells you which role and privilege it needs:
-- Signed-in users manage their own notes; signed-out visitors get nothing
grant select, insert, update, delete on table public.notes to authenticated;
alter table public.notes enable row level security;
-- ...plus one policy per operation (see our RLS guide)
Replace notes with your table. Grant only what each role needs. Only grant to anon for data that's meant to be public.
What we tested (October 16, 2026): without a grant, a signed-out read failed with 42501: permission denied for table notes and the hint "Grant the required privileges to the current role with: GRANT SELECT ON public.notes TO anon;". A public table with grant select ... to anon, RLS on and a read-only policy returned its rows to anon.
Why it happens
Docs-only, except where marked
Postgres checks grants before policies. Supabase's RLS guide says a missing grant "raises a 42501 error before any policy runs", so check grants before you change policies (Supabase: RLS).
To see a table's grants (Supabase: 42501 errors):
select grantee, privilege_type
from information_schema.role_table_grants
where table_name = 'notes';
Verified: on the same test container, this listed the roles and privileges for the table.
Why you may see it more on tables created on or after October 30, 2026: Supabase applies a changed default to all existing projects on that date. Existing tables keep their current grants and stay reachable. Only tables created in public after the change need an explicit grant before the Data API can see them. Direct Postgres connections are unaffected (Supabase changelog). Our Oct 30 grants guide covers the migration pattern.
Clients often surface 42501 as a 401 or 403, so read the response body for permission denied for table (Supabase: 42501 errors). Not every 42501 is a missing grant: Supabase also lists restricted schemas, custom schemas without API grants, column-level restrictions, and RLS blocking an insert or update. If the message says "new row violates row-level security policy", see our RLS error fix.
If you limited updates to certain columns on purpose, for example so users can't change their own role, a 42501 on those columns is that protection working. See Never let users edit the field your access rule trusts.
What not to do
Docs-only
- Don't disable RLS.
- Don't grant everything to
anonwithout policies. - Don't move the secret or
service_rolekey into the frontend (Supabase: API keys).
Treat grant + enable RLS + policies as one unit in the same migration (Supabase changelog).
Copy this fix
-- Replace notes with your table. Signed-out visitors get nothing.
grant select, insert, update, delete on table public.notes to authenticated;
alter table public.notes enable row level security;
-- ...plus one policy per operation (see our RLS guide)
Grant only what each role needs, and keep RLS on. Policy examples: Supabase row-level security, explained for builders.
Related
- new row violates row-level security policy
- Supabase's Oct 30 change: new tables need a GRANT
- infinite recursion detected in policy for relation (42P17)
Educational, not a security audit. Platforms change: check the linked sources. Disclaimer.
Top comments (0)