A restore didn't bring back Storage files
SupaHost restores roll back a project's database but not its Storage files. Why deleted files stay gone, what "Object not found" after a restore means, and how to protect files.
What you see
You restored a project to a point before some files were deleted. The database is back, and the files show up again in Studio's Storage browser and in this query:
select bucket_id, name, created_at
from storage.objects
order by created_at desc;
But downloading them fails, with an error from the Storage API instead of the file. Or the reverse: files uploaded after the restore point don't appear in listings any more.
Why it happens
A project's files and its database are stored in different places:
- The database, including the
storage.objectstable that lists every file and its metadata, is in Postgres. Daily backups and point-in-time recovery cover it. - The file contents are on your instance's disk. They aren't part of the daily backups.
A restore rolls back the database only. After a restore:
| File was... | Its row in storage.objects |
The file on disk | Result |
|---|---|---|---|
| Deleted after the restore point | Back | Still gone | Listed, but downloads fail |
| Uploaded after the restore point | Gone | Still there | Not listed or served |
| Unchanged | Same | Same | Works |
Files replaced after the restore point can also end up out of step with their metadata, so check any you know were overwritten.
How to fix it
Find the objects whose files are gone. On the project's Backups tab, click Package files. When the download is ready, open the archive: if any objects have no file, it includes a
missing.txtlisting them.Put those files back from your own copies, using the same bucket and path:
const { error } = await supabase.storage .from("recipe-photos") .upload("user-42/lasagne.jpg", file, { upsert: true });Use
upsert: true, because the row already exists.If you can't recover a file, delete its row so your app stops linking to it:
await supabase.storage.from("recipe-photos").remove(["user-42/lasagne.jpg"]);Check your app's own tables too. If a
recipes.photo_pathcolumn points at a file that's gone, update or clear it.
Protecting files from now on
- Click Package files on the Backups tab regularly, or before risky changes, and keep the archive somewhere safe. It holds every file plus
buckets.jsonandobjects.jsonwith bucket settings and metadata. Download links last 24 hours. - For files you can't lose, also keep a copy outside SupaHost: for example, upload originals to your own object storage as well, or sync them on a schedule.
- Deleting from Storage is permanent. If users can delete files, consider a soft delete (a
deleted_atcolumn, cleaned up later) so mistakes can be undone. See Implementing soft deletes.
On SupaHost
- Restores touch one project. Other projects' databases and files aren't affected.
- The database from before the restore is kept for 3 days and then dropped.
- Taking a Create pg_dump export just before a restore gives you your own record of
storage.objects(and everything else) as it was. - Branches created with Copy data, users and files get a real copy of the parent's files, so they don't have this problem.