Fixes › Database / Supabase RLS
Supabase Storage upload fails: new row violates row-level security policy (403)
The error
StorageApiError: new row violates row-level security policy (403 Unauthorized)
Why it happens
Supabase Storage is protected by RLS on storage.objects. A bucket without INSERT policies rejects uploads even when it's 'public' (public only affects reads).
How to fix it
- Add an INSERT policy on storage.objects for the bucket, e.g. allowing authenticated users to upload into a folder named after their user id.
- Upload to a path like `${user.id}/${filename}`.
- Add SELECT/UPDATE/DELETE policies as needed (upsert needs UPDATE).
- Keep the bucket private if files aren't meant to be public, and use signed URLs.
Fix prompt (paste into Lovable, Bolt, Cursor, Replit or v0)
Uploads to the Supabase Storage bucket <BUCKET> fail with a row-level security 403. Add storage.objects policies so authenticated users can insert, read, update and delete only files under a folder named with their auth.uid(), change the upload code to use the path `${user.id}/<filename>`, and give me the SQL.
FAQ
The bucket is public, why 403?
Public only affects downloads; uploads still need policies.
How do I restrict to own folder?
Use (storage.foldername(name))[1] = auth.uid()::text in the policy.
Related fixes
- Supabase query returns an empty array (no error)
- new row violates row-level security policy for table
- Supabase Edge Function fails with CORS or 'Failed to send a request'
- Postgres error: relation "public.xyz" does not exist
Want the full checklist for this area? Get a Fix Kit ($29)
Featured slot available: reach thousands of vibe coders. Sponsor this week →
Get one new fix a week
Free newsletter: the newest breakages in Lovable, Bolt, Cursor, Replit and v0 apps, with paste-in fixes.
We only use your email to send the newsletter. Unsubscribe any time. See privacy.