跳到正文
DEV Community· fixkit ai·· 3 小時前AI 評分58

Lovable 和 Bolt 應用中的 Supabase RLS 錯誤及安全修復方法

Supabase RLS errors in Lovable and Bolt apps (and how to fix them safely)

AI 導讀

這篇指南説明如何診斷及安全修復 Lovable 或 Bolt 應用中的 Supabase RLS 錯誤。被阻止的 select 會靜默回傳空結果,而 insert 會出現錯誤碼 42501。指南建議以 auth.uid() 限制用戶操作自己的資料列,並確認用戶已登入及 user_id 正確;不要停用 RLS,也不要在前端使用 service_role key。

正文

fixkit ai

If you built your app with Lovable or Bolt on top of Supabase, sooner or later you'll see this:

new row violates row-level security policy for table "todos"

That's Postgres error code 42501. Its quieter cousin is worse: a select that returns [] with no error, even though the table clearly has rows.

Why it happens

When Row Level Security (RLS) is enabled and no policy allows an action, Supabase blocks it. Common causes in AI-built apps:

  • RLS is enabled but no insert/select policy exists
  • The user isn't logged in, so auth.uid() is null
  • The insert doesn't set user_id, or sets it to a different value
  • An update policy is missing its with check

Reads and writes fail differently. A blocked select doesn't throw; rows are filtered out and you get []. A blocked insert throws the error above.

Fix 1: add owner-based policies

Run this in the Supabase SQL editor (rename todos to your table):

alter table public.todos enable row level security;

create policy "Users read own todos" on public.todos
for select to authenticated using ((select auth.uid()) = user_id);

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

create policy "Users update own todos" on public.todos
for update to authenticated
using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id);

create policy "Users delete own todos" on public.todos
for delete to authenticated using ((select auth.uid()) = user_id);



Fix 2: fill in user_id automatically

alter table public.todos alter column user_id set default auth.uid();



Fix 3: make sure the user is actually signed in

const { data: { user } } = await supabase.auth.getUser();
if (!user) throw new Error('Not signed in');
await supabase.from('todos').insert({ title, user_id: user.id });



Don't "fix" it by disabling RLS or shipping the service_role key

The service_role key (and the newer sb_secret_... keys) bypasses RLS entirely. Keep it on the server only, never in frontend code. The browser should only use the anon or publishable key, and that key is only safe because RLS limits what it can do.

Prompt to paste into Lovable or Bolt

Write Supabase RLS policies so authenticated users can only select, insert, update, and delete rows where user_id = auth.uid(). Don't disable RLS and don't use the service_role key in the client.

FAQ

Why do I get empty results instead of an error? RLS filters select results silently. With no policy, you get zero rows.

Is a public read policy OK? Yes, for genuinely public data: for select to anon, authenticated using (true).


Originally published on FixKit AI. If you're seeing a different error, paste it into the free FixKit Error Fixer (disclosure: I built it). Related: CORS errors when a Lovable app calls an API.

來源:DEV Community · dev.to