Guide
Supabase: new row violates row-level security policy on insert
Updated
Supabase's docs say to enable RLS, revoke the default grants from anon and authenticated, then grant back only the operations your app needs, and write a separate policy for each operation. A missing grant raises a 42501 error before any policy runs, so check the grants before you change the policy.
Fixed in your code, then tested live. Check my app free
Why it happens
Policies are Postgres's rule engine and are added to every query on the table. Postgres runs two checks before a client touches a table: grants decide whether a role can run an operation at all, and policies decide which rows it applies to. A table in an exposed schema without RLS is readable and writable by any role with a grant on it, and adding policies does not take those grants back.
Possible causes
- The request runs as anon because the user is not signed in or the session has expired, so auth.uid() returns null and a policy comparing it to a column is false.
- A grant is missing for the role making the request, which raises a 42501 error before any policy runs.
- The policy is not scoped to the role the request uses, so it does not apply to that request.
- The insert policy's with check expression does not match the values in the new row.
- A Supabase Storage upload sets upsert to true and no select policy covers the object, so the database cannot return the row and the upload fails with a 403 policy violation.
Official fix steps
- Enable row level security on the table in an exposed schema. (supabase.com)
- Revoke all existing grants on the table from anon and authenticated. (supabase.com)
- Grant back only the privileges each role needs, such as select, insert, update and delete for authenticated. (supabase.com)
- Write a separate policy for select, insert, update and delete, and name the role each policy applies to. (supabase.com)
- For insert, use a with check expression that the new row must satisfy. (supabase.com)
- Check the grants before you change the policy when a request fails that your policy should allow. (supabase.com)
- Create a test file for the table under supabase/tests and run the test suite, fixing what it reports. (supabase.com)
- For a Storage upload, leave upsert at its default of false if you do not need to overwrite files. If you do need to overwrite, keep upsert true and add a select policy on storage.objects that mirrors your insert policy. (supabase.com)
You can't see it yourself
You're signed in, your customers aren't. Supabase maps every request to a role: anon for a request where the user is not signed in, and authenticated for a request where the user is signed in. Grants and policies apply by role, so what your own signed-in session can do does not show what a signed-out visitor's request runs into.
What to do next
App broke after you published it? Our AI agent fixes it in your code, then tests your live app again so you see the result yourself. The first check is free.
Fixed in your code, then tested live. Check my app free
Related: "new row violates row-level security policy" fix · Edits or upserts blocked by row-level security · RLS error saving a profile right after sign-up
Sources
VibeFix's check can show this on your live app: its AI agent signs up to your app like a new person, uses it on a phone and a computer, and shows what breaks.
Last checked: 1 November 2026, against the sources listed above.
VibeFix is independent. Lovable, Bolt, Replit, Base44, v0 and Supabase are trademarks of their owners.
Want it fixed?
Our AI agent fixes it in your code and tests your live app again. See pricing.
It starts with a free check that confirms the problem on your live app, no account needed.