Question

Bolt + Supabase: new row violates row-level security policy for table "profiles"

Solved · 416 viewsasked by mcflyy

Signup works, user appears in Auth. Then my code inserts the profile row and I get:

Bolt made this policy:

create policy "Users can insert own profile" on profiles
  for insert with check (auth.uid() = id);

Looks right to me?

What I’ve tried

Asked Bolt to fix, it suggested disabling RLS on profiles. I did not do that because I read that's bad. Tried logging in first and then inserting, same error.

Comment
Is email confirmation turned on in your Auth settings? jb_supa
no idea, where do I see that mcflyy

3 answers

Marked as helpful by the asker
jb_supa

The policy is fine, the timing isn't. If "Confirm email" is on in Supabase Auth, signUp() returns a user but no session. Your insert right after runs as anon, so auth.uid() is null and the check fails.

Cleanest fix: create the profile in the database with a trigger, so the client never has to:

create function public.handle_new_user()
returns trigger language plpgsql security definer set search_path = ''
as $$
begin
  insert into public.profiles (id, username)
  values (new.id, new.raw_user_meta_data->>'username');
  return new;
end;
$$;

create trigger on_auth_user_created
  after insert on auth.users
  for each row execute function public.handle_new_user();

Pass username via options.data in signUp. Remove the client-side insert.

And good call not disabling RLS.

Comment
Confirm email was on yes. Trigger works, profile appears on signup now. mcflyy
+1 on the trigger. The set search_path = '' bit matters, keep it. hannah_reyes
amir_h

Side note for later: once you have that trigger, drop the insert policy on profiles entirely. Users never need to insert their own profile then, one less door open.

Comment
arash

Had exactly this. For testing you can turn off email confirmation in the Auth settings so signups get a session immediately, but switch it back on before real users arrive.

Comment