ShipShape

Guide · 30 October 2026

Supabase stops auto-exposing new tables on 30 October 2026

New tables in the public schema of an existing Supabase project will not be exposed to the Data API unless you GRANT them. supabase-js then fails with 42501. Turning off row level security is the wrong fix.

What changes, and when

Supabase published the breaking change on 28 April 2026. New projects stopped exposing new public tables by default on 30 May 2026. On 30 October 2026 the same setting is applied to existing projects. The source is their changelog, Tables not exposed to Data and GraphQL API automatically.

Until then, a new table in public was reachable from the Data API because Postgres granted select, insert, update, and delete to anon, authenticated, and service_role. After the change, a new table exists but the API cannot see it until you grant the role you actually want.

Existing tables keep the grants they already have. Altering a table does not strip them. A project with no flagged tables today still breaks the first time someone creates a new one in public and expects supabase-js to read it.

What 42501 means

PostgREST answers a missing grant with 42501 and permission denied for table your_table. The hint names the statement, for example GRANT SELECT ON public.your_table TO anon. Supabase documents that response in the changelog and in Database API 42501 errors. The failure happens before any row level security policy runs.

Grants and a policy, together

This is the shape Supabase shows: a grant for the role, RLS enabled, then a policy. Rename the table and the user column. anon gets read only here. service_role bypasses RLS, so keep that key on the server and grant it only in server migrations, not in the browser.

-- Rename your_table and user_id. Do not disable row level security.
grant select on public.your_table to anon;
grant select, insert, update, delete on public.your_table to authenticated;

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

If an insert fails because the identity column’s sequence is not granted, add grant usage, select on sequence public.your_table_id_seq to authenticated. That is a sequence grant, not a reason to turn RLS off.

What ShipShape Scan does with this

The free check and the Launch Report do not connect to your database and do not test policies. If the public page contains a Supabase URL, the report says so and the paid report includes this SQL to paste. You still run it yourself in the SQL editor. A weekly Monitor rescan repeats the same passive check. It will not notice a missing grant.

Questions

Do existing tables lose access on 30 October 2026?

No. Supabase says existing tables keep their current grants and stay reachable. The change is for new tables created in the public schema after the setting is on.

What error does supabase-js show when the grant is missing?

PostgREST returns code 42501, "permission denied for table your_table", with a hint that names the GRANT. Clients often surface that as a failed request. Row level security has not run yet.

Should I disable row level security to fix 42501?

No. Disabling RLS does not grant the role access. If you then add a broad GRANT, the table is open. Add the narrow GRANT, leave RLS enabled, and add a policy for the rows that role should see.

Does this affect a direct Postgres connection?

Supabase says no. Apps that talk to Postgres with a connection string, psql, or an ORM do not use the Data API. supabase-js, the other client libraries, and HTTP calls to /rest/v1/ or /graphql/v1 do.

Run a free check