Vai al contenuto

Basi della sicurezza

Supabase "Bucket not found": le tre cose che può voler dire

Supabase "Bucket not found" è una di tre cose: un link pubblico a un bucket privato, un nome non esattamente uguale o il progetto sbagliato.

Vlad Tkachenko10 min di lettura
Uno scaffale di bucket, uno chiuso con un lucchetto. Davanti, un'etichetta ambra la cui linea tratteggiata si ferma contro una barra.

In breve

  • Supabase "Bucket not found" significa che Storage ha cercato un bucket con esattamente quel nome, nel progetto raggiunto dalla tua richiesta, e non ne ha trovato nessuno che fosse disposto a servire a quella richiesta. Il bucket può benissimo essere lì, nella tua dashboard.
  • Un link creato con getPublicUrl per un bucket privato dà questo errore quando lo apri, perché Storage serve quei link solo dai bucket pubblici.
  • Su un upload significa che il nome manca in quel progetto. Controlla l'ortografia e le maiuscole, poi a quale progetto punta la tua app.
  • Rendere pubblico il bucket fa sparire il messaggio e permette a chiunque abbia l'indirizzo di un file di aprirlo. Per i file che appartengono a una sola persona, usa un link firmato.

La tua app mostra un'immagine rotta dove dovrebbe esserci una foto. Oppure un upload fallisce, e il messaggio che torna indietro è lungo tre parole: "Bucket not found". Allora apri Supabase, vai su Storage, e il bucket è proprio lì, nell'elenco.

Apri l'indirizzo dell'immagine in una scheda a parte e Storage risponde così:

{
  "statusCode": "404",
  "code": "NoSuchBucket",
  "error": "Bucket not found",
  "message": "Bucket not found"
}

Questo è il corpo che costruisce oggi il codice sorgente di Supabase Storage, letto il 17 ottobre 2026. Supabase "Bucket not found" copre tre situazioni diverse con questo stesso corpo, e nella prima il bucket è esattamente dove l'hai lasciato.

Ed ecco il punto su cui guida dopo guida sbaglia: la prima soluzione che troverai è rendere pubblico il bucket, e quando funziona, funziona perché ogni file di quel bucket diventa pubblico a sua volta. Per due delle tre cause non cambia assolutamente nulla. Per quella che resta, scambia un'immagine rotta con un bucket che chiunque abbia l'indirizzo di un file può leggere.

Che cosa significa Supabase "Bucket not found"?

Storage ha cercato un bucket con esattamente il nome della tua richiesta, nel progetto raggiunto dalla tua richiesta, e non ne ha trovato nessuno che fosse disposto a servire a quella richiesta.

Quell'ultima parte c'è perché un bucket ha più di una porta, e ogni porta pone la domanda a modo suo. Il codice sorgente di Storage ne mostra tre:

  • Un indirizzo pubblico di file, quello che crea getPublicUrl. Questa porta conta solo i bucket segnati come pubblici, quindi un bucket privato qui è "non trovato" anche se esiste.
  • Un upload. Questa porta conta tutti i bucket del progetto, privati compresi. "Non trovato" qui significa che quel nome manca davvero da quel progetto.
  • Una richiesta dell'elenco dei file di un bucket. Questa porta non dice mai "Bucket not found". Un bucket che non esiste risponde con un elenco vuoto, la stessa risposta di un bucket vuoto, e lo vediamo da fuori ogni volta che il nostro scanner lo chiede.

Il primo compito è quindi capire da quale porta è passata la richiesta che è fallita.

I due numeri di quel messaggio non coincidono, e questo inganna la gestione degli errori. Il corpo dice "statusCode": "404", mentre la richiesta in sé fallisce con lo stato HTTP 400. Storage invia questo errore con un 400 e tiene il proprio 404 nel corpo. La libreria supabase-js passa entrambi al tuo codice: error.status vale 400 ed error.statusCode vale "404". Il codice che il tuo builder ha scritto per intercettare un 404 lascerà passare questo.

È la causa dietro le immagini rotte. L'indirizzo è stato costruito per un bucket pubblico, e il bucket è privato.

getPublicUrl non chiede nulla a Supabase. Mette insieme l'indirizzo del tuo progetto, il nome del bucket e il nome del file in un link, dentro la tua app, e te lo restituisce. La nota sopra quella funzione, nella libreria client di Supabase, lo dice in due frasi:

Questa funzione non verifica se il bucket è pubblico. Se viene creato un URL pubblico per un bucket che non è pubblico, non potrai scaricare il file.

Più tardi il browser di un visitatore chiede quel link, e Storage cerca il bucket solo tra i bucket pubblici. Un bucket privato non supera questa ricerca, proprio come uno che non esiste, e la risposta è "Bucket not found".

Puoi riconoscere questa causa dal link stesso. Un indirizzo pubblico di file contiene /storage/v1/object/public/ seguito dal nome del bucket. Se quel bucket non porta alcuna indicazione di pubblico in Storage → Buckets, il link non si sarebbe mai aperto, comunque sia scritto il nome.

I bucket nuovi nascono privati, quindi l'impostazione si sta comportando come previsto. Quello che è successo è che il codice, tuo o del tuo builder, è stato scritto per un bucket pubblico e puntato su uno privato.

Un solo bucket privato, due modi di chiedere un file. L'indirizzo pubblico viene respinto alla porta, e il link firmato passa fino allo stesso file.

Causa 2: un nome che non è proprio quello del bucket

Storage confronta il nome del bucket carattere per carattere, quindi Avatars e avatars sono due bucket diversi, e lo stesso vale per avatar e avatars.

Nel codice sorgente di Storage la ricerca è una semplice uguaglianza sull'id del bucket. Le maiuscole contano, una lettera mancante conta, e un trattino dove il bucket ha un trattino basso conta. Ognuno di questi casi torna indietro con le stesse tre parole.

Un'app costruita con uno strumento di IA può arrivare qui senza che nessuno abbia sbagliato a scrivere. Il codice che carica o mostra un file viene scritto in un passaggio, e il bucket che nomina dovrebbe essere creato in un altro. Se quel secondo passaggio non è mai avvenuto, o è avvenuto con un nome leggermente diverso, il codice chiede un bucket che nessuno ha creato.

Il controllo richiede due elenchi. Apri Storage → Buckets e annota il nome di ogni bucket esattamente com'è scritto. Poi di' al tuo builder, con parole semplici: elenca ogni nome di bucket Storage che questa app usa, e mostrami dove viene usato ciascuno. Qualsiasi nome del suo elenco che manca dal tuo è quello che fallisce.

Causa 3: il bucket è in un altro progetto

La tua app parla con un solo progetto Supabase, quello del suo indirizzo Supabase, e un bucket creato in qualunque altro progetto per la tua app semplicemente non esiste.

È su un upload che questa causa si vede più chiaramente. In un upload, Storage cerca il bucket in tutto il progetto senza applicare le tue regole di accesso, quindi "Bucket not found" su un upload non è mai un problema di permessi. Quando il bucket esiste e le tue regole rifiutano il file, Storage risponde con un altro messaggio, che parla di row-level security. Quindi "Bucket not found" su un upload significa che quel nome manca dal progetto in cui scrive la tua app.

Ci sono modi del tutto normali per ritrovarsi con due progetti: un progetto di prova accanto a quello in produzione, una copia dell'app collegata a un progetto nuovo, un progetto creato a mano per provare qualcosa. Il bucket viene creato in quello che in quel momento era aperto nella dashboard.

Il controllo è un confronto tra due stringhe corte. L'indirizzo Supabase della tua app ha la forma https://<ref>.supabase.co, e la parte prima di .supabase.co è il riferimento del progetto. L'indirizzo della tua dashboard porta lo stesso riferimento dopo /project/. Se i due sono diversi, stai guardando un progetto mentre la tua app parla con un altro.

Il bucket esiste. È stato creato nel progetto di destra, e ogni richiesta della tua app va a quello di sinistra.

Conviene rendere pubblico il bucket per risolvere?

Solo quando ogni file del bucket è pensato per chiunque abbia il suo indirizzo, e solo per la prima causa. Con un nome sbagliato o un progetto sbagliato, l'interruttore non cambia nulla.

Un bucket pubblico fa una sola cosa, e la documentazione di Supabase la descrive in una riga: chiunque possieda l'indirizzo di un file può aprirlo. Non c'è di mezzo nessun accesso. Gli esempi che dà Supabase stessa sono foto profilo, media pubblici e contenuti di articoli del blog, e loghi o foto dei prodotti rientrano nello stesso gruppo.

È l'impostazione sbagliata per fatture, scansioni di documenti d'identità, esportazioni o qualsiasi cosa appartenga a una sola persona. L'interruttore vale per l'intero bucket e per ogni file che ci arriverà dopo, compresi i file di una funzione che devi ancora costruire.

La stessa scorciatoia ha un gemello dal lato delle regole, ed è quello che misuriamo. Una regola su storage.objects che nomina solo il bucket fa funzionare i download per tutti, e consegna anche l'elenco dei nomi nel bucket. Abbiamo scansionato 8.435 app online che nominano un progetto Supabase. Il controllo dei bucket ha avuto una risposta da 4.703 di queste, e 792 hanno risposto alla nostra richiesta di elenco con i nomi di ciò che c'era dentro, senza nessuno connesso. È circa una su sei delle app a cui abbiamo potuto chiedere. Quando un bucket è pubblico e anche il suo elenco è aperto, ogni nome di quell'elenco è un link che funziona.

Come mostrare un file privato senza renderlo pubblico

Dai alla pagina un link firmato: un indirizzo che funziona per il numero di secondi che scegli e poi smette di funzionare.

La documentazione di Supabase indica due modi per far uscire un file da un bucket privato. Uno è un download che porta con sé la sessione della persona che ha effettuato l'accesso. L'altro è createSignedUrl, che crea un link "a cui si può accedere per un tempo limitato". È questo secondo a prendere il posto di getPublicUrl ovunque una pagina mostri un'immagine.

Anche un link firmato risponde alle tue regole. Prima che Storage firmi qualsiasi cosa, il suo codice sorgente controlla che la persona che lo chiede possa leggere quel file, quindi un bucket privato ha bisogno di una regola select su storage.objects che dica chi può leggere cosa. L'errore di upload spiega come si scrivono queste regole, compreso perché una regola di lettura che nomina solo il bucket ne apre anche l'elenco.

Per passarlo al tuo builder, con parole semplici: per il bucket che dà l'errore "Bucket not found", sostituisci getPublicUrl con createSignedUrl, lascia il bucket privato e aggiungi una policy di Storage che permetta a ogni persona di leggere solo i file che deve vedere. Poi ricarica la pagina che aveva l'immagine rotta.

Che cosa mostrano adesso i tuoi bucket agli estranei

Due schermate della dashboard ti dicono che cosa hai impostato, e un controllo da fuori ti dice che cosa ottiene un estraneo.

Storage → Buckets mostra quali bucket sono pubblici. Per ognuno, chiediti se ogni file che contiene è qualcosa che mostreresti a un estraneo. Storage → Policies mostra le regole. Una regola select la cui unica condizione è il nome del bucket permette a chiunque di leggere quel bucket, elenco dei file compreso.

La nostra scansione gratuita chiede al tuo progetto online l'elenco dei file di ogni bucket usando solo la chiave che è già nel codice della tua app, come farebbe un estraneo, e ti dice quali bucket hanno risposto con dei nomi. Legge nomi e non scarica mai un file. Ci vogliono circa 20 secondi e non serve un account: scansiona la tua app.

Tenere i tuoi file dove li hai messi

Dopo la correzione di oggi possono ancora muoversi due cose: qualcuno cambia un'impostazione mentre insegue un altro bug, e viene cancellato un file che a qualcuno serviva.

Reeve Monitor continua a controllare da fuori:

  • il controllo di sicurezza completo, ripetuto secondo una pianificazione, compreso quello sull'elenco dei bucket
  • se la tua app risponde
  • un messaggio quando un risultato cambia, così un bucket che si è aperto durante la notte non aspetta che tu vada a guardare
  • un report mensile, in linguaggio semplice, di ciò che ha visto

Reeve Care tiene una copia di ciò che c'è dentro:

  • una copia cifrata del tuo database Supabase secondo una pianificazione, sullo storage di Reeve nell'UE, fuori dal tuo account Supabase
  • ogni copia verificata prima che conti, contando le righe di ogni tabella
  • anche i file caricati, appena colleghi una credenziale di Storage
  • un ripristino con un clic, con una copia di sicurezza dello stato attuale fatta prima
  • tutto ciò che fa Monitor

Che cosa fare oggi

Cosa fare

  • Apri il link che fallisce in una scheda a parte. Se l'indirizzo contiene /storage/v1/object/public/ e il bucket è privato, è la prima causa.
  • Copia il nome del bucket da Storage → Buckets e confrontalo, maiuscole comprese, con il nome che usa la tua app.
  • Confronta il riferimento del progetto nell'indirizzo Supabase della tua app con quello nell'indirizzo della tua dashboard.
  • Lascia un bucket privato a meno che ogni file che contiene sia pensato per chiunque abbia il suo indirizzo, e servi i file privati tramite link firmati.
  • Leggi ogni regola select su storage.objects. Una che nomina solo il bucket consegna anche l'elenco dei file.

Comincia dalla richiesta che è fallita, perché la porta da cui è passata ti dice quale delle tre cause controllare. La checklist di sicurezza in 10 minuti copre ciò che un'app appena lanciata tende a lasciare aperto oltre a questo, e che cosa espone un bucket pubblico è la lettura successiva se uno dei tuoi si è rivelato pubblico.

FAQ

Perché Supabase dice che il mio bucket non esiste se lo vedo?

Perché Storage cerca un bucket in modo diverso a seconda della richiesta. Un indirizzo pubblico di file, quello che crea getPublicUrl, viene cercato solo tra i bucket pubblici, quindi un bucket privato che vedi nella dashboard lì risulta non trovato. Se invece l'errore è arrivato da un upload, il nome nel tuo codice non corrisponde esattamente a nessun bucket del progetto a cui è collegata la tua app.

Il nome di un bucket Supabase distingue maiuscole e minuscole?

Sì. Storage confronta il nome carattere per carattere, quindi Avatars e avatars sono due bucket diversi, e lo stesso vale per avatar e avatars. Copia il nome da Storage → Buckets nella tua dashboard e confrontalo con il nome che usa la tua app.

Devo rendere pubblico il bucket per risolvere "Bucket not found"?

Solo se ogni file che contiene è pensato per chiunque abbia il suo indirizzo, come foto profilo o foto dei prodotti. Pubblico significa che chiunque abbia l'indirizzo di un file può aprirlo senza accedere. Risolve l'errore solo quando è stato creato un link pubblico per un bucket privato; un nome sbagliato o un progetto sbagliato restano rotti comunque. Per i file che appartengono a una sola persona, lascia il bucket privato e usa un link firmato.

Come mostro un file di un bucket privato?

Con un link firmato. createSignedUrl crea un indirizzo che funziona per il numero di secondi che scegli e poi smette di funzionare, e prende il posto di getPublicUrl ovunque una pagina mostri il file. Chi chiede il link deve poter leggere il file, quindi il bucket ha bisogno di una regola select su storage.objects che dica chi può leggere cosa.

Perché l'errore dice 404 se la richiesta è fallita con 400?

Supabase Storage invia questo errore con lo stato HTTP 400 e mette il proprio stato, 404, nel corpo come statusCode. In supabase-js arriva come error.status 400 ed error.statusCode "404", ed è per questo che il codice scritto per intercettare un 404 lascia passare questo errore senza accorgersene.

Scritto da

Vlad Tkachenko

Fondatore di Reeve

Passo le giornate a guardare app costruite con Lovable, Bolt, v0, Cursor e Replit, e la breve lista di errori che vi ricompaiono di continuo.

Altro sull'autore

Da leggere dopo

Tutti gli articoli

Fai il backup del database Supabase prima della prossima modifica

Reeve ne tiene una copia cifrata a intervalli programmati e la ripristina per te se qualcosa va storto.

Vedi i backup Supabase

Controllo esterno automatizzato, non un audit completo. L'assenza di risultati non è una garanzia di sicurezza.