Why the data shows in Supabase but not in your app
The Supabase table editor uses an admin role that skips RLS, so you can see every row. Your app uses the public (anon or publishable) key, so RLS applies. With RLS on and no SELECT policy, the query succeeds and returns an empty list instead of an error. That makes it look like the data vanished.
Why inserts fail
An INSERT needs a policy with a WITH CHECK clause that the new row passes. A common pattern ties each row to the signed-in user with a user_id column. If the app never sets user_id, or the user isn't signed in yet, the check fails.
-- Each user can read and add their own rows
create policy "Read own rows" on public.notes
for select to authenticated
using ((select auth.uid()) = user_id);
create policy "Add own rows" on public.notes
for insert to authenticated
with check ((select auth.uid()) = user_id);Not sure which of these it is? We'll tell you in 24 hours, free.
Get a free health checkWhat not to do
Don't turn RLS off to make the error go away. With RLS off, anyone who has your public key, which ships inside your app, can read and change that table. Write the policy instead.
A quick check you can run today
Open your Supabase project and look at the Security Advisor. It flags tables in exposed schemas that have RLS turned off and policies that look risky. Fix those first.
Questions people ask
Is it safe that my Supabase anon key is visible in the browser?
The anon or publishable key is designed to be public, but only when RLS is on and every table has policies. The service_role or secret key must never be in browser code because it bypasses RLS completely.
Why does my Supabase query return an empty array with no error?
RLS is enabled and no SELECT policy allows the current user to see those rows. Add a SELECT policy, or check that the user is signed in when the query runs.