New Row Violates Row-Level Security Policy? Fix It (2026)
You click Save in your app and nothing happens. The console shows code: 42501 and the message new row violates row-level security policy for table “notes”. Reads work, sign-in works, but every insert, upsert or file upload fails. If your app was built with Lovable, Bolt, v0 or Cursor on Supabase, the causes and fixes below are the same.
The good news: it is almost never a bug in Supabase. Postgres is doing exactly what Row Level Security (RLS) is for. The row you are trying to write does not pass a WITH CHECK rule, or no rule allows that write at all. This guide shows how to find which one, with copy-paste SQL for each case. If your problem is users seeing each other’s data instead, read Supabase RLS not working. If the error says permission denied for table, read Supabase permission denied for table.
Quick answer: The insert is running as a role that no INSERT policy allows, or the new row fails the policy’s WITH CHECK. Sign the user in before writing, set user_id with default auth.uid(), add an INSERT policy to authenticated with check ((select auth.uid()) = user_id), and add SELECT (plus UPDATE for upsert) policies when you chain .select() or upsert.
| What you see | Most likely cause | Check | Fix |
|---|---|---|---|
.insert() fails while signed in | No INSERT policy, or user_id missing so the check compares to null | Does the payload or column default set user_id? | Add INSERT policy, set default auth.uid() |
| Fails when signed out or on first page load | Request runs as anon, so auth.uid() is null | Call supabase.auth.getUser() right before the insert | Wait for the session, require sign-in |
.insert() works, .insert().select() fails | No SELECT policy that matches the new row | List policies in pg_policies | Add a SELECT policy for the owner |
.upsert() fails, .insert() works | Upsert also needs SELECT and UPDATE policies | Are SELECT and UPDATE policies present? | Add SELECT + UPDATE with the same owner check |
.update() throws the same error | UPDATE WITH CHECK rejects the changed row | Is the code changing user_id? | Keep user_id, add USING + WITH CHECK |
| Storage upload returns 403 | No INSERT policy on storage.objects, or wrong folder | Bucket id and file path vs the policy | Add storage policies, upload to userId/file |
| Server code with the secret key still fails | A user session took over the Authorization header | SSR client or signUp on the admin client? | Use a separate admin client |
permission denied for table instead | Missing grant, not a policy | Query role_table_grants | See permission denied fix |
Want it fixed for you? Launch Mango moves your Lovable, Bolt, v0 or Cursor app onto your own GitHub, Supabase and Vercel accounts and makes it safe for real users. Own and Secure is $199 one-off: everything in Own Your App plus sign-in and redirects, Supabase RLS and permissions locked down, exposed API keys removed, live Stripe payments and webhooks, a security report and your custom domain included. Not sure where your app stands? Run the free 2-minute app check.
What Does “New Row Violates Row-Level Security Policy” Mean?
It means Postgres refused to write a row because Row Level Security is on for that table and the new r
