---
title: "File uploads fail or storage returns 403"
description: "Supabase storage blocks uploads to buckets without policies and private files need signed URLs. How to check your bucket policies and fix 403s safely."
url: https://whocanfixmyapp.com/problems/file-uploads-fail-or-return-403
---

[Home](https://whocanfixmyapp.com/) / [Problems](https://whocanfixmyapp.com/problems) / [Data and database](https://whocanfixmyapp.com/problems#data-and-database)

# File uploads fail or storage returns 403

VC-44 · Supabase · Lovable · Updated October 2026 · By [Nathaniel Kelley](https://whocanfixmyapp.com/authors/nathaniel-kelley)

Quick verdict

Partly fixable yourself. One or two storage policies, written in SQL

- **How serious**: Medium
- **Fix it yourself?**: Partly, some steps need a developer
- **Typical cost**: $49–$800 one-off check, or €99–$990 for a single fix ([prices](https://whocanfixmyapp.com/pricing))
- **Top rated for Supabase**: [Redlab](https://whocanfixmyapp.com/companies/redlab) · **10.0**/10

**What you see.** Uploading an avatar or document fails, or files upload but images show broken with a 403 or 400 from storage.

## Why it happens

Supabase Storage is protected by the same Row Level Security as your tables, applied to the `storage.objects` table. Supabase states that Storage does not allow any uploads to buckets without RLS policies, and buckets are private by default. So a bucket the AI created with no policies rejects every upload, and a private bucket rejects every plain download link.

The details trip builders up. An upload needs an `INSERT` policy. Overwriting a file, which the code calls upsert, also needs `SELECT` and `UPDATE`. Reading from a private bucket needs a signed URL or the user's token, not a direct link. Buckets can also restrict file size and content types, which produces failures that look like permission errors. The common AI shortcut is to make the bucket public or to use the secret key, which turns a 403 into a leak of everyone's files.

## Fix it yourself

1. In the Supabase dashboard open **Storage**, select the bucket, then **Policies**. Check there is an `INSERT` policy for the `authenticated` role on this bucket.
2. If the code overwrites files, add `SELECT` and `UPDATE` policies for the same users, since upsert needs all three.
3. Decide what the bucket holds. Public things such as avatars and product images can live in a public bucket. Invoices, documents and anything personal stay private and are shown through signed URLs.
4. Scope uploads to the user. Ask the builder to store files in a folder named after the user's id and to restrict the policy to that folder.
5. Check the bucket's file size and allowed content type limits. A 5 MB phone photo against a 1 MB limit fails before any policy runs.
6. Test with two accounts. One user should not be able to open or list the other user's files.

## When to get an engineer

Hire an engineer when files are mixed in one bucket with no ownership, when the app already used the secret key to make uploads work, or when private files were served from a public bucket. Tell them which buckets exist, what each holds, and who should see what. A one-off check costs $49–$800. Writing the policies and switching the app to signed URLs is a single fix at €99–$990, about two days of work.

## Top-rated companies for Supabase apps

Ranked by our score: published prices, scope of work, AI tools named, timing and a low-risk first step. [How we score](https://whocanfixmyapp.com/methodology#score).

- 1 · [Redlab](https://whocanfixmyapp.com/companies/redlab) · **10.0**/10 · Best for: A full rescue by one team that keeps building · Free first step · from $490
- 2 · [Vibe Code Rescue (Lev Arakelyan)](https://whocanfixmyapp.com/companies/vibe-code-rescue-lev-arakelyan) · **9.0**/10 · Best for: A one-off check and a cleanup · From $299
- 3 · [LazyCodeLab](https://whocanfixmyapp.com/companies/lazycodelab) · **9.0**/10 · Best for: A one-off check and a cleanup · From $399

[All 29 Supabase companies, ranked](https://whocanfixmyapp.com/best/supabase-developers)

## Check these

DATA-04 · High

File storage is private where it should be

Upload a private file, copy its URL, and open it in a private window. If it loads, the bucket is public.

DATA-01 · Critical

Access rules are on for every table

In Supabase, open Table Editor: every table should show RLS enabled, with at least one policy. In Firebase, your rules should never say `allow read, write: if true`.

DATA-03 · Critical

One user cannot open another user's records

Sign in as user A, copy a request from the Network tab, and change the record ID to one that belongs to user B. You should get an error or an empty result.

DATA-02 · Critical

No secret keys reach the browser

Open your live app, then DevTools, Sources, and search the loaded JavaScript for `sb_secret_`, `sk_live_`, `sk-proj-` and `sk-ant-`. Older Supabase keys are long tokens starting with `eyJ`: decode the middle part of each on your own machine, and if it contains `"role":"service_role"`, your secret key is public. A publishable or anon key in the browser is expected.

## Questions

### Is making the bucket public an acceptable fix?

Only if every file in it should be visible to anyone with the link. Supabase says public buckets skip access control for reads, while uploads and deletes still follow your policies.

### Are my uploaded files included in database backups?

No. Supabase's database backups do not include objects stored through the Storage API, so download or copy files separately.

Sources: [Supabase docs: Storage Access Control](https://supabase.com/docs/guides/storage/security/access-control); [Supabase docs: Storage Buckets fundamentals](https://supabase.com/docs/guides/storage/buckets/fundamentals); [Supabase docs: Database Backups](https://supabase.com/docs/guides/platform/backups).

**Lovable guide**

What Lovable builds, where it breaks and how to check it: [Lovable app rescue: what breaks and how to check it](https://whocanfixmyapp.com/guides/lovable).

**Same category**

- [My Supabase service_role key is in the browser](https://whocanfixmyapp.com/problems/supabase-secret-key-in-the-browser)
- [Data saves with no error but never shows up](https://whocanfixmyapp.com/problems/data-saves-with-no-error-but-never-shows-up)
- [Supabase project paused or free tier limit reached](https://whocanfixmyapp.com/problems/supabase-project-paused-or-free-tier-limit)
- [I have no backups and don't know how to restore](https://whocanfixmyapp.com/problems/no-backups-and-i-dont-know-how-to-restore)
- [Test data and real customer data are in one database](https://whocanfixmyapp.com/problems/test-data-mixed-with-real-customer-data)
- [Firebase rules are set to allow read, write: true](https://whocanfixmyapp.com/problems/firebase-rules-allow-read-write-true)

[All data and database problems](https://whocanfixmyapp.com/problems#data-and-database)

**Run every check**

The [production checklist](https://whocanfixmyapp.com/checklist) has all 24 checks with a verdict.
