Supabase: new row violates row-level security policy
The error
new row violates row-level security policy for table "todos"
What it means
You tried to INSERT a row, RLS is enabled on the table, and no policy permits the current user to write what you tried to write.
When you enable RLS, every action defaults to denied. INSERT requires a WITH CHECK policy that returns true for the row you’re inserting. Common mistake: a SELECT policy exists, but no INSERT policy, so reads work but writes fail.
The fix
-- Allow users to insert their own todo
CREATE POLICY "users insert own todo"
ON public.todos
FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- And make sure the inserted row sets user_id from the JWT, not the client
-- (you can use a default: user_id uuid DEFAULT auth.uid())Also check
Common adjacent root causes when the obvious fix doesn’t work.
- 01Are you signed in? auth.uid() returns NULL for unauthenticated users; most policies fail.
- 02Did your client set the row’s user_id field correctly? Many clients send NULL by default.
- 03Are there separate policies for INSERT, UPDATE, DELETE? FOR ALL covers all four; FOR INSERT covers only inserts.
Scan for related issues
This error is in our supabase scanner. Run a free scan to find what else is misconfigured in the same area.
FAQ
Frequently asked questions
- Can I just disable RLS to make this go away?
- You can, but then your table is open to anyone with your anon key — which ships in your client bundle. Almost always the wrong move. Add the right policy instead.
- How do I debug which policy is blocking me?
- Run EXPLAIN on the query in Supabase SQL Editor — it shows which policies were evaluated. Or temporarily switch the role to postgres and rerun: if it works, RLS is the cause.
Related fixes
Tighten this area further
Supabase RLS disabled
A Supabase table without RLS is readable (and often writable) by anyone with your anon key. Here is exactly how to turn on RLS and write your first policy.
Read moreExposed Supabase service key
The service role key bypasses all security in Supabase. If it is in your client code, an attacker has full database access. Here is how to find and fix it.
Read moreBackground
Concepts
Row Level Security
RLS is a Postgres feature that Supabase uses to enforce per-row access control. With RLS off, the anon key gives anyone full table access.
Read moreSupabase
An open-source backend-as-a-service built on Postgres. Popular with AI tools for its simple API, but RLS misconfigurations are common.
Read more