Rowpass 42501: permission denied for table Not affiliated with Supabase

Rowpass / Guides

Local tables missing grants after db reset

A reset replays your migrations. Without grants in them, tables come back closed.

The local setting

A Supabase maintainer wrote in the announcement thread (2026-06-08) that CLI v2.102.0 added a local equivalent of the cloud toggle, in config.toml:

[api]
auto_expose_new_tables = false

Set to false, supabase start and supabase db reset run the same revoke statements the dashboard runs at project creation. Left unset, you get automatic exposure, and the maintainer said the implicit default would flip to match the cloud default during the rollout.

Do not build on this setting. In the same thread on 2026-06-12, a Supabase maintainer confirmed that auto_expose_new_tables is "a temporary migration aid and scheduled for removal on 2026-10-30". If your CLI version no longer accepts the key, remove it from config.toml.

Source: maintainer comments of 2026-06-08 and 2026-06-12 in the GitHub discussion, read 2026-11-10, not the reference docs. We have not checked which CLI release removes the field.

The fix that survives every reset

The same maintainer's advice: put explicit grants in a migration, because a migration replays on every db reset. For tables from older migrations, add one new migration that grants them. For new tables, grant in the migration that creates them.

-- 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 );

Paste your whole schema into the tool below to get one migration that covers every table.

Write the fix for your tables

One table is free. The whole schema with a rollback file is $9 one-time, free during launch.

 

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.

    Questions

    Do the revoke statements touch my existing local tables?

    No. They change default privileges, which only apply to objects created afterwards. After a reset, every table is created afterwards, which is why they all come back without grants.

    Sources

    Related

    Did it fix your error?