Supabase Permission Denied for Table (42501): The Fix
Error 42501 means the role making the request (usually anon or authenticated) has no GRANT on that table. Add only the grant you need and keep RLS on.

On this page
- What does "permission denied for table" mean in Supabase?
- Why did this start happening?
- What does "permission denied for schema public" mean in Supabase?
- How do you fix Supabase 42501 step by step?
- 1. Read the hint
- 2. Check which grants the table has
- 3. Grant only what the feature needs
- 4. Make sure RLS is on and has policies
- 5. Retry and confirm
- What does a before and after look like?
- What quick fixes should you avoid?
- Why does it fail on my local stack or preview but work in production?
- What if I built the app with an AI tool?
- How can you check which tables still need grants before Oct 30?
- Where should you go next?
- FAQ
Short answer: Supabase "permission denied for table" (Postgres error 42501) means the role making the request, usually anon or authenticated, has no GRANT on that table. Since Supabase's change, new tables in the public schema aren't reachable through the Data API until you grant access, and the change reaches every existing project on Oct 30, 2026. The fix is one line, for example grant select on public.your_table to authenticated;, with row level security left on.
By Gary, Greenlight 路 Last checked against the Supabase changelog and docs: Oct 20, 2026 路 Drafted with AI tools and reviewed before publishing.
This page is the fix for the error itself. For the full background on the change and a checklist, read our main guide: Will Supabase's October 30 change break your app?
Table names in this guide (like notes, posts or your_table) are made-up examples. Swap in your own.
What does "permission denied for table" mean in Supabase?
When a grant is missing, the Data API (PostgREST, which supabase-js calls) returns an error like this, taken from Supabase's own changelog (Supabase changelog (external)):
{
"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;"
}Code 42501 is Postgres's "insufficient privilege" error. Supabase's troubleshooting page says clients often report it as a 401 or 403, and that "permission denied for table your_table" means the querying role may not have the privilege for that operation (Supabase docs (external)).
Why did this start happening?
Supabase used to grant select, insert, update and delete on every new public table to the anon, authenticated and service_role roles automatically. Supabase changed that default in stages (Supabase changelog (external)):
| Date | What changed |
|---|---|
| Apr 28, 2026 | Optional at project creation |
| May 30, 2026 | Default for new projects (gradual rollout) |
| Oct 30, 2026 | Applied to all existing projects |
Two details matter. Existing tables keep their current grants, so only tables created after the change reaches your project are affected. And if your app only talks to Postgres over a direct connection (psql, an ORM or a server connection string), you aren't affected at all (Supabase changelog (external)).
What does "permission denied for schema public" mean in Supabase?
It's the same 42501 error one level up. In Postgres, a role needs the USAGE privilege on a schema before it can reach any table inside it, even a table it has grants on (PostgreSQL docs (external)). Supabase projects normally give anon, authenticated and service_role usage on public, so this message usually means that usage was revoked, or the table lives in a custom schema the roles were never given. The fix is the schema grant, then the table grants below:
grant usage on schema public to anon, authenticated;If the schema is your own (not public), use its name, and remember a custom schema also has to be exposed in your project's Data API settings before supabase-js can call it.
How do you fix Supabase 42501 step by step?
1. Read the hint
The hint field names the missing role and privilege. Treat it as a starting point, not an order: the example hint grants to anon, which may be wider than you want.
2. Check which grants the table has
Run this in the SQL editor (Supabase docs (external)):
select grantee, privilege_type
from information_schema.role_table_grants
where table_schema = 'public'
and table_name = 'your_table';No rows for anon or authenticated means the Data API can't reach the table for those roles.
3. Grant only what the feature needs
Decide who should use the table and what they should do with it. For a private table that signed-in users read and write:
grant select, insert, update, delete on table public.your_table to authenticated;For a read-only public table, such as published blog posts:
grant select on table public.posts to anon, authenticated;The privilege names come from the PostgreSQL GRANT command (PostgreSQL docs (external)). Our guide to which grants anon, authenticated and service_role need has a role-by-role table.
4. Make sure RLS is on and has policies
alter table public.your_table enable row level security;Supabase's docs say that granting privileges opens the table to the Data API, so you should enable RLS and write policies to protect the data (Supabase docs (external)). A grant without RLS lets that role reach every row. New to policies? Start with what is Supabase RLS?
5. Retry and confirm
Reload the app or repeat the request. If you now get an empty list instead of an error, the grant worked and RLS is filtering rows; check your policies next. That difference is explained in Supabase GRANT vs RLS.
What does a before and after look like?
A worked example with a new notes table (an example) created after the change. Each row shows what a signed-in user would get, based on how Supabase describes grants and RLS:
| Step | Request as a signed-in user | Result |
|---|---|---|
| Table created after the change, no grant | select * from notes via supabase-js | 42501 permission denied |
grant select ... to authenticated added, RLS off | same | every user's notes (unsafe) |
| RLS on, "read own notes" policy | same | only that user's notes |
The middle row is the trap. The error goes away, the app "works", and every signed-in user can read every note.
What quick fixes should you avoid?
- Turning RLS off. It doesn't fix 42501 (grants are a separate layer), and once you add a grant it exposes every row.
grant all ... to anon. It hands the public key every table privilege, includingtruncateandtrigger, which a browser should never need (PostgreSQL docs (external)). Grantselect,insert,updateordeleteindividually.- Using the service role key in the browser. It bypasses RLS (Supabase docs (external)). If it ever shipped to the client, follow our service role key guide.
- Re-enabling auto-exposure everywhere. The change exists so tables aren't exposed before they're secured. Add grants per table in your migrations instead.
Why does it fail on my local stack or preview but work in production?
When your schema is rebuilt from migrations, every table is created fresh, so tables lose the grants the old default used to add. See Supabase db reset permission denied for the migration fix.
What if I built the app with an AI tool?
The changelog calls this out: if an AI coding tool, CLI script or Management API call creates tables and expects them to be reachable, you need to act (Supabase changelog (external)). Our plain-English guide is Lovable or Bolt app says permission denied.
How can you check which tables still need grants before Oct 30?
Supabase says Security Advisor will flag affected tables and that it will email active projects (Supabase changelog (external)). You can also use our Oct 30 checker and the checklist in our Oct 30 change guide.
Where should you go next?
Next, decide which role gets what with Supabase grants for anon and authenticated, and write policies with Postgres row level security: a Supabase guide. If a secret key ever reached your frontend, see Supabase service role key exposed?. Building with AI tools? Our Lovable launch checklist and what is vibe coding? cover the rest of a pre-launch pass, and the hub for this change is Will Supabase's October 30 change break your app?
FAQ
Does this affect tables I already have? No. Supabase says existing tables keep their current grants and stay reachable.
Is the anon key the problem? No. The key is meant to be public; see is my Supabase anon key safe?. The role behind it just has no grant on the new table.
Does 42501 always mean a missing grant?
No. Supabase's docs list other causes, such as querying restricted schemas like auth or a custom schema that isn't exposed.
I get no error, just empty results. Is that the same issue? No. Empty results with no error usually mean RLS is on and no policy matches the user.
Sources
On this site
Related posts

Lovable Supabase Permission Denied? Fix for Bolt Apps Too
A Lovable or Bolt app saying Supabase permission denied usually means a new table has no GRANT. A safe prompt for your AI tool and how to check it.

Postgres Row Level Security: A Supabase Guide
Postgres row level security decides which rows each user can read or change. Set it up in Supabase, write policies and fix common errors.

Supabase db reset: Fix Permission Denied After Oct 30
Supabase db reset permission denied (42501) happens because rebuilt tables no longer get default grants. Add GRANTs to migrations and retest.
Get the next change before it bites
Greenlight tips and new blog posts: short, practical notes when Supabase, Lovable, Bolt, Cursor or another tool you build with changes something that affects your app, plus what to check. About twice a month.
We'll send a confirmation email first. Unsubscribe anytime. Privacy. Greenlight My App is independent and not affiliated with or endorsed by Supabase, Lovable, Bolt, Cursor or any other tool we mention.
Greenlight is independent and not affiliated with or endorsed by Supabase, PostgreSQL, Lovable or Bolt. Product names are used only to identify the tools this guide is about. Code is example SQL; test it on a copy of your project before running it in production. This page is general information, not professional security advice, legal advice, a security audit or a guarantee. Check your own setup against the vendor's current docs.