Supabase 42501: permission denied for table
42501: permission denied for table your_table
In short: The role your app is using (usually anon or authenticated) has no table-level GRANT, so the Data API rejects the request before RLS even runs.
Why it happens
Since 30 October 2026, new tables in the public schema are no longer auto-exposed to Supabase's Data API. select, insert, update, and delete used to be granted to anon, authenticated, and service_role on every new public table. Now you have to GRANT those privileges yourself. Existing tables keep their old grants. AI migrations often create the table, enable RLS, and add policies, then skip the GRANT, so supabase-js returns 42501 permission denied for table. This is not the same error as new row violates row-level security policy: Postgres checks grants first, and RLS only runs after the role is allowed to touch the table at all.
How to fix it
- Read the error body. If the message is
permission denied for table …, you are missing a GRANT (or you are querying a forbidden schema such asauth). If it isnew row violates row-level security policy, that is an RLS policy problem, not this one. - In the SQL editor, check who can do what:
select grantee, privilege_type from information_schema.role_table_grants where table_schema = 'public' and table_name = 'your_table';Replaceyour_tablewith the real name. - Grant only what each role needs, then keep RLS on. A typical authenticated app looks like this:
grant select, insert, update, delete on public.your_table to authenticated;andgrant select, insert, update, delete on public.your_table to service_role;. Grant toanononly for data that should be readable or writable while signed out (for example a public waitlist insert). - Enable RLS if it is not already on, and add policies that match those grants, for example
create policy "own rows" on public.your_table for select to authenticated using (auth.uid() = user_id);. Put the GRANT,enable row level security, and the policies in the same migration so the next AI-created table does not repeat this. - Retry the same request from the app (not only the SQL editor). The editor often runs as
postgres, which can still succeed whenanoncannot. If the hint names a different role, grant that role, not a broader one.
Example
-- Run in the SQL editor. Swap your_table and adjust privileges per role.
grant select, insert, update, delete on public.your_table to authenticated;
grant select, insert, update, delete on public.your_table to service_role;
-- grant select, insert on public.your_table to anon; -- only if signed-out users need it
alter table public.your_table enable row level security;
create policy "users can read their own rows"
on public.your_table for select to authenticated
using (auth.uid() = user_id);
create policy "users can write their own rows"
on public.your_table for insert to authenticated
with check (auth.uid() = user_id);
grant all on public.your_table to anon or by turning RLS off. That makes the 42501 go away and can leave the table readable or writable by anyone who has your public anon key.Copy-paste fix prompt
I'm getting this error in my app: 42501: permission denied for table your_table [Paste the full error, stack trace, and the file it points to here] Likely cause: The role your app is using (usually anon or authenticated) has no table-level GRANT, so the Data API rejects the request before RLS even runs. Task: The error is 42501 permission denied for table, which is a missing GRANT on a new public table (Supabase no longer auto-grants Data API access as of 30 Oct 2026), not an RLS policy failure. Add explicit GRANTs for only the roles and privileges this table needs, keep RLS enabled, and add policies that use auth.uid() where rows are per-user. Do not GRANT ALL to anon and do not disable RLS. Rules: - First explain the root cause in 2 sentences and list the files you'll change. - Make the smallest change that fixes it. Don't refactor unrelated code. - Don't disable security or checks (RLS, auth, signature verification, type checking, CORS allow-all) to make the error disappear. - Never print or hard-code secret keys. - Finish by telling me exactly how to verify the fix.
Common with: Cursor, Lovable, Bolt, Claude Code, v0. Last reviewed 2026-11-15.