Guides / Supabase
Supabase 42501 "permission denied" after October 30
Last reviewed · VibeShield
Short answer: from October 30, 2026, Supabase stops automatically granting new public tables to the anon, authenticated and service_role roles in existing projects. A table you create after the change exists, but the Data API (supabase-js, REST, GraphQL) can't reach it until you GRANT access. Until then you get error 42501. The fix is to grant only the privileges each role needs, enable RLS and add policies, table by table. Don't run a bulk grant on the whole schema.
The error looks like this (Supabase changelog):
{
"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 hint names the role and privilege that's missing.
What changed on October 30, 2026
Supabase's changelog gives the timeline: the opt-in became available April 28, 2026; on May 30, 2026 it "starts to become the default for all new projects," as a gradual rollout over a few weeks; and "On October 30, 2026 the setting will be applied it to all existing projects" (quoted as written).
What it means in practice:
- New tables in
public"require an explicit opt-in (via a Postgresgrant) before the Data API can see them." - Existing tables "are not affected in your project, they keep their current grants and stay reachable."
- RLS doesn't change. "Grants are a separate layer: they control whether a role can access a table at all, while RLS controls which rows that role can see."
- Direct Postgres connections (psql, an ORM, an app server with a connection string) are not affected.
- The
storage,auth,realtimeand custom schemas "keep their current grants and their current defaults."
Supabase's stated reason: "agents, CLI scripts, and AI platforms create tables too, and many of those operations do not have a human reviewing the diff." If Lovable, Bolt, Cursor or another AI tool creates your tables, this change probably explains the error.
Step 1: confirm it's a missing grant
42501 has several causes. Supabase's 42501 troubleshooting article lists them: a forbidden schema (such as auth or vault), a custom schema not exposed to the API, missing table-level privileges, column-level restrictions (including select * touching a restricted column), and RLS blocking an INSERT or UPDATE.
Check what roles can do on the table in the SQL Editor:
select grantee, privilege_type from information_schema.role_table_grants where table_schema = 'public' and table_name = 'your_table';
If anon or authenticated is missing from the results, the cause is a missing grant. To see recent 42501 errors across the project, the same article gives a logs query:
select
timestamp,
event_message,
log_attributes['parsed.error_severity'] as error_severity,
log_attributes['parsed.user_name'] as user_name,
log_attributes['parsed.query'] as query,
log_attributes['parsed.detail'] as detail,
log_attributes['parsed.hint'] as hint
from logs
where
source = 'postgres_logs'
and log_attributes['parsed.error_severity'] in ('ERROR', 'FATAL', 'PANIC')
and log_attributes['parsed.sql_state_code'] = '42501'
order by timestamp desc
limit 100;Step 2: grant, enable RLS and add policies, as one unit
Supabase says to "treat these three steps as a unit. If the grant is missing, Postgres rejects the query before RLS comes into play." Here is a least-privilege version for a table where signed-in users manage their own rows and signed-out visitors need nothing:
-- 1. Grant only what each role needs (nothing for anon here) grant select, insert, update, delete on public.your_table to authenticated; -- 2. Enable RLS alter table public.your_table enable row level security; -- 3. Add policies for every operation you granted create policy "Users can view their own rows" on public.your_table for select to authenticated using ((select auth.uid()) = user_id); create policy "Users can create their own rows" on public.your_table for insert to authenticated with check ((select auth.uid()) = user_id); create policy "Users can update their own rows" on public.your_table for update to authenticated using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id); create policy "Users can delete their own rows" on public.your_table for delete to authenticated using ((select auth.uid()) = user_id);
The (select auth. form and the to authenticated clause follow the RLS docs.
Only grant anon for genuinely public data, for example grant select on public. plus a matching for select to anon policy. Supabase warns that to anon using (true) "grants every unauthenticated visitor read access to every row the role can already reach through grants."
Server code needs a grant too. The API keys docs say "A missing grant returns a permission error, including for service_role." If an Edge Function or backend uses the secret key on the new table, grant service_role only what that code uses:
grant select, insert on public.your_table to service_role;
Sequences. If your table uses a serial/bigserial id, roles that insert also need the sequence: Postgres's nextval "requires USAGE or UPDATE privilege on the sequence" (Postgres docs). The changelog also handles sequence grants separately from table grants:
-- Only the roles that insert rows (here: signed-in users and your server code) grant usage, select on sequence public.your_table_id_seq to authenticated, service_role;
Check the real sequence name with select pg_. Identity columns (generated always as identity or generated by default as identity) don't need a sequence grant: Postgres uses their sequence internally.
Don't use the bulk rollback as a 42501 fix
The changelog FAQ has a rollback for people who opted in early and broke their app. Its second block grants select, insert, update and delete on all tables in schema public to anon, authenticated and service_role. (We don't reproduce it as runnable SQL on purpose.)
This undoes the protection. It gives anon full read and write grants on every table in public. The RLS docs say "A table in an exposed schema without RLS is readable and writable by any role with a grant on it." So any table without RLS, or with a loose policy, becomes reachable by anyone holding your publishable key. Supabase's own follow-up step is to "revoke those individually after the bulk grant," which is easy to forget. Grant per table instead.
Step 3: stop your AI tool from causing it again
Supabase suggests that if an AI coding tool creates your tables, you "update its system prompt or adopt the Supabase agent skill, which includes the grants step." A project instruction like this works in Lovable, Bolt or Cursor:
Whenever you create a table in the Supabase public schema, include in the same migration: enable row level security; explicit per-table GRANTs only to the roles that need them; owner-scoped RLS policies; and sequence grants for serial ids. Never use "on all tables in schema public" grants. If you hit 42501, add a narrow grant for that one table and role.
Step 4: verify
- Re-run the
role_query and confirm each role has only what you intended.table_ grants - Open Security Advisor. Supabase said that in the run-up to October 30 it "flags affected tables per project and shows the remediation SQL." Also check
0013 rls disabled in publicand0024 permissive rls policy(Advisors). - Test your app signed out, and as two different test users, to confirm each user sees only their own rows.
Check what your own site exposes
The free VibeShield passive check reads your page's HTML and up to 10 same-origin JavaScript bundles. It flags leaked secrets, including Supabase service_role and secret keys, and missing security headers. It doesn't log in, probe your database or write data.
Use it on your own app only. You must confirm you own it or are authorized to test it. A passive check can't see your grants or RLS policies, so the SQL above is how you verify those. A clean result doesn't mean your app is secure.
If you'd like it re-run automatically, the founding plan ($19/mo founding price, cancel anytime) emails your first report within minutes of subscribing. It then re-checks every Monday and emails what's new, fixed and still open, with copy-paste fix prompts that grant per table and enable RLS. There's also a free waitlist.
FAQ
Will my existing tables break on October 30?
According to Supabase, no. Existing tables "keep their current grants and stay reachable." Only tables created after the change need explicit grants.
Why does my server (service_role) also get 42501?
Grants are checked first for every role, including service_role. It bypasses RLS, not grants. Grant it the privileges your server code uses on each new table.
Does this affect storage buckets or the auth schema?
Not by this change. Supabase says storage, auth, realtime and custom schemas keep their current grants and defaults.
I use Prisma or Drizzle over a connection string. Do I need to do anything?
Not for direct connections. The change only affects the Data API. If any part of your app also uses supabase-js, those tables need grants.
Can I just turn off RLS to make the error go away?
No. RLS isn't what causes this error; the missing grant is. Turning RLS off, and then granting, leaves the table open to any role with a grant.
Is the bulk grant ever OK?
Supabase gives it as a rollback for early opt-ins. It re-opens every public table to anon. If you've checked that every table has RLS and correct policies, it's less risky, but per-table grants are safer and easier to review.
How do I find which new tables lack grants?
Use Security Advisor, the Data API exposure badge in the Table Editor (both mentioned in the changelog), or the role_ query above.
Sources
- Supabase changelog, "Breaking Change: Tables not exposed to Data and GraphQL API automatically": https://supabase.com/changelog/45329
- Supabase KB, Database API 42501 errors: https://supabase.com/kb/troubleshooting/database-api-42501-errors
- Supabase, Row Level Security: https://supabase.com/docs/guides/database/postgres/row-level-security
- Supabase, API keys: https://supabase.com/docs/guides/getting-started/api-keys
- Supabase, Advisors: https://supabase.com/docs/guides/observability/advisors
- PostgreSQL, Sequence functions: https://www.postgresql.org/docs/current/functions-sequence.html
All sources loaded on October 28, 2026. VibeShield is not affiliated with Supabase, Lovable or Bolt.