Error library

Supabase RLS: empty results or 'new row violates row-level security policy'

With RLS enabled and no matching policy, Postgres denies by default: reads return an empty array and writes fail with error 42501. Add a policy for each operation (select, insert, update, delete) for the right role, and make sure the request carries the signed-in user's session.

Cause: RLS is on but no policy allows this role and operation, or the row fails the policy's with check, or an insert chained with .select() has no SELECT policy.

How to fix it

  1. Check which policies exist for the table and role (authenticated vs anon).
  2. Add one policy per operation; inserts use with check, updates need using + with check and a SELECT policy.
  3. Ensure the client is signed in so auth.uid() is set, and the row's user_id matches.
  4. If you chain .select() after an insert to get the row back, you also need a SELECT policy.
  5. Never fix this by using the service_role key in the browser.

Example

Illustrative example, not from a customer project.

+ create policy "own rows: select" on public.todos
+   for select to authenticated using ((select auth.uid()) = user_id);
+ create policy "own rows: insert" on public.todos
+   for insert to authenticated with check ((select auth.uid()) = user_id);

FAQ

Why do I get [] instead of an error?

A using clause that filters out every row returns zero rows silently. Only grants and with check violations raise 42501.

Should I just disable RLS?

No. Tables exposed through the API without RLS can be read by anyone holding your public anon key.

Get a $149 diagnosis See pricing Still exposed or still logged out? Get an auth & database security fix (Supabase, Firebase).

$149Get a $149 diagnosis