#11 most commondatabaseLovableBolt.newCursorReplitv0Windsurf
permission denied for table (Supabase 42501, missing GRANT)
{"code":"42501","message":"permission denied for table todos","hint":"Grant the required privileges to the current role with: GRANT SELECT ON public.todos TO anon;"}
Got a slightly different error? Paste the exact message and get a fix prompt tailored to it.
Paste your error →What it means
Your app's users (the 'anon' and 'authenticated' roles) haven't been given access to this table at all, so the database refuses before it even looks at your security rules. Supabase no longer gives new tables that access automatically: it's the default for projects created since May 30, 2026 and applies to all existing projects from October 30, 2026. Tables that already existed keep working; newly created ones need an explicit GRANT.
How to fix it: paste this prompt into your AI builder
Fix prompt for Lovable, Bolt, Cursor, Replit, v0, Windsurf
My Supabase request fails with 42501 "permission denied for table". This is a missing table GRANT, not an RLS policy problem. Do NOT disable RLS, do NOT run GRANT ALL, and do NOT grant anything to anon unless signed-out visitors genuinely need it. Steps: (1) For the table in the error, show me its current grants (select grantee, privilege_type from information_schema.role_table_grants where table_schema = 'public' and table_name = '<table>') and whether RLS is enabled. (2) Write ONE migration that, as a unit: grants only the operations the app actually uses, e.g. grant select, insert, update, delete on public.<table> to authenticated; grant select on public.<table> to anon ONLY if the data is public and read-only; grant select, insert, update, delete to service_role only if server code uses it; if inserts use a serial/identity id, grant usage, select on the matching sequence to the same roles. (3) In the same migration: alter table public.<table> enable row level security, and add policies scoped to the owner (using ((select auth.uid()) = user_id) / with check ((select auth.uid()) = user_id)). (4) Update our table-creation convention so every future CREATE TABLE in public ships with its GRANTs, RLS and policies together. Never put the service_role key in browser code. Explain which roles got which privileges and why before applying.
If the AI can't fix it: manual steps
- Supabase SQL Editor: run select grantee, privilege_type from information_schema.role_table_grants where table_schema = 'public' and table_name = 'your_table'; If anon/authenticated are missing, that's the cause.
- Grant only what's needed, e.g. grant select, insert, update, delete on public.your_table to authenticated; and, only for public read-only data, grant select on public.your_table to anon; (inserting into a table with a serial id also needs grant usage, select on sequence public.your_table_id_seq to authenticated;)
- Keep RLS on: alter table public.your_table enable row level security; then add policies, e.g. create policy "own rows" on public.your_table for all to authenticated using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id);
- If the error says 'violates row-level security policy' instead, the grant is fine and you need an RLS policy (see the RLS entry). The Supabase Security Advisor and the Table Editor's Data API exposure badge list tables missing grants.
Where this happens
Seen in these AI app builders and editors:
LovableBolt.newCursorReplitv0Windsurf
Sources
Related database errors
Still stuck? Paste your full error and UnstuckMyVibe will match it and hand you the exact fix prompt.
Fix my error →