Rowpass 42501: permission denied for table Not affiliated with Supabase

Rowpass / Guides

42501: permission denied for table

The role has no grant on the table. Paste the error or your table and get the SQL.

Write the fix for your tables

 

Waiting for a paste.

    Who can reach each table

    Your tables show up here, one row each, with a choice of who can reach them.

    The SQL appears here as soon as a table is found.

    Parsed in your browser. Your SQL is never uploaded, and no site or database is scanned.

    What the error says

    {
      "code": "42501",
      "message": "permission denied for table your_table",
      "hint": "Grant the required privileges to the current role with: GRANT SELECT ON public.your_table TO anon;"
    }

    The Data API (the REST layer that supabase-js calls) runs each request as a database role. If that role has no privilege on the table, Postgres rejects the query before it looks at any row level security policy. The hint names the role and the privilege that is missing.

    Why it started now

    • Before: every new table in public was granted to anon, authenticated and service_role automatically.
    • After the change: a new table has no grants until you write them. The Data API answers 42501, permission denied for table.
    • Tables that already existed keep their grants. Row level security works as before.
    DateWhat happensWho it reaches
    2026-04-28Changelog published. A setting at project creation lets you turn automatic exposure off.New projects that opt in
    2026-05-30The new behavior becomes the default for all new projects (gradual rollout over a few weeks).New projects
    2026-10-30The new behavior is enforced on all existing projects.Every project that uses the Data API

    Dates are from the Supabase changelog post published 2026-04-28, read 2026-11-10. We have not seen an official post confirming that the 2026-10-30 step finished for every project, so check your own project with this query.

    The fix, in order

    Supabase's guidance is to treat three steps as one unit: grant, enable row level security, add policies.

    -- public.your_table: owner only
    alter table public.your_table enable row level security;
    revoke all on table public.your_table from anon, authenticated;
    grant select, insert, update, delete on table public.your_table to authenticated;
    grant select, insert, update, delete on table public.your_table to service_role;
    drop policy if exists your_table_select_own on public.your_table;
    create policy your_table_select_own on public.your_table
      for select to authenticated
      using ( (select auth.uid()) = user_id );
    drop policy if exists your_table_insert_own on public.your_table;
    create policy your_table_insert_own on public.your_table
      for insert to authenticated
      with check ( (select auth.uid()) = user_id );
    drop policy if exists your_table_update_own on public.your_table;
    create policy your_table_update_own on public.your_table
      for update to authenticated
      using ( (select auth.uid()) = user_id )
      with check ( (select auth.uid()) = user_id );
    drop policy if exists your_table_delete_own on public.your_table;
    create policy your_table_delete_own on public.your_table
      for delete to authenticated
      using ( (select auth.uid()) = user_id );

    That is the "owner only" shape. The tool writes the same structure for public-read and private tables, and names your real table and owner column.

    It is not always a missing grant

    42501 is the Postgres code for "insufficient privilege". Supabase lists other causes too. See all 42501 causes in one table.

    Questions

    Do I need to change my RLS policies?

    Not for this error. A missing grant fails before any policy runs. Check the grants first, then the policies.

    Why did old tables keep working?

    The change only affects new tables. Existing tables keep the grants they already have.

    Can I just grant everything to anon and authenticated?

    It makes the error go away, and it also makes the table reachable by every visitor unless row level security and policies restrict it. Grant each role only what it needs.

    Sources

    Related

    Did it fix your error?