Fix guides / Supabase: "new row violates row-level security policy"
How to fix "new row violates row-level security policy" in Supabase
Your app worked in the preview, then saving a record fails with error code 42501 and the message new row violates row-level security policy for table. Here is what it means and how to fix it without opening your database to the world.
What the error means
Supabase tables have Row Level Security (RLS). When RLS is on and no policy allows an action, Postgres refuses it. An insert fails with 42501: new row violates row-level security policy. This is a safety feature, not a bug in Supabase. AI builders often turn RLS on (good) but forget to add an insert policy, or write one that does not match how the app sends data.
The 3 most common causes
- No INSERT policy at all. There is a SELECT policy, so reading works, but nothing allows writing.
- The user is not logged in when the insert runs. The request uses the anon role, so
auth.uid()is null and a policy likeauth.uid() = user_idfails. - The app does not send
user_id, or sends a different value than the logged-in user's id.
Step 1: check your policies
In the Supabase dashboard open Authentication, then Policies, and find the table. Or run this in the SQL editor:
select policyname, cmd, roles, qual, with_check from pg_policies where tablename = 'your_table';
Step 2: add a safe insert policy
For a table where each row belongs to a user (a user_id uuid column referencing auth.users):
create policy "Users can insert their own rows" on public.your_table for insert to authenticated with check ( (select auth.uid()) = user_id );
Better still, let the database fill in the owner so the app cannot get it wrong:
alter table public.your_table alter column user_id set default auth.uid();
Then the front end can insert without sending user_id at all.
Step 3: make sure the request is authenticated
Log the session right before the insert:
const { data: { session } } = await supabase.auth.getSession();
console.log('logged in as', session?.user?.id);
If this prints undefined, the insert runs as anon. Fix the login flow, or wait for the session to load before saving.
What not to do
- Do not disable RLS to make the error go away. Anyone with your public anon key (it ships in your front end) could then read and change every row.
- Do not add a policy
with check (true)for the anon role unless the table is meant to be a public form, like a waitlist, and even then limit the columns. - Do not put the
service_rolekey in front-end code. It bypasses RLS completely.
Quick checklist
- RLS on, with explicit SELECT, INSERT, UPDATE, DELETE policies as needed
- Insert policy targets
authenticated user_iddefaults toauth.uid()- Session exists when the insert runs
Request a fix
Last updated 2026-10-19.