Zum Inhalt springen

Sicherheitsgrundlagen

Supabase "Bucket not found": die drei Dinge, die es bedeutet

Supabase "Bucket not found" ist eins von drei Dingen: ein öffentlicher Link zu einem privaten Bucket, ein ungenauer Name oder das falsche Projekt.

Vlad Tkachenko10 Min. Lesezeit
Ein Regal mit Buckets, einer mit Schloss. Davor ein bernsteinfarbenes Adressschild, dessen gestrichelte Linie vor einer Sperre endet.

Kurz gesagt

  • Supabase "Bucket not found" heißt, dass Storage nach einem Bucket mit genau diesem Namen gesucht hat, in dem Projekt, das deine Anfrage erreicht hat, und keinen gefunden hat, den es dieser Anfrage ausliefern würde. Der Bucket kann trotzdem in deinem Dashboard stehen.
  • Ein Link, den getPublicUrl für einen privaten Bucket gebaut hat, liefert beim Öffnen genau diesen Fehler, weil Storage solche Links nur aus öffentlichen Buckets bedient.
  • Bei einem Upload heißt es, dass der Name in diesem Projekt fehlt. Prüf die Schreibweise und die Großbuchstaben, dann, auf welches Projekt deine App zeigt.
  • Den Bucket öffentlich zu machen beendet die Meldung und lässt jeden, der die Adresse einer Datei hat, diese Datei öffnen. Für Dateien, die einer Person gehören, nimm einen signierten Link.

Deine App zeigt ein kaputtes Bild, wo ein Foto sein sollte. Oder ein Upload scheitert, und die Meldung, die zurückkommt, ist drei Wörter lang: "Bucket not found". Dann öffnest du Supabase, gehst zu Storage, und der Bucket steht genau da in der Liste.

Öffne die Adresse des Bildes in einem eigenen Tab, und Storage antwortet so:

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

Das ist der Body, den der Quellcode von Supabase Storage heute baut, gelesen am 17. Oktober 2026. Supabase "Bucket not found" deckt mit diesem einen Body drei verschiedene Situationen ab, und in der ersten liegt der Bucket genau dort, wo du ihn gelassen hast.

Und hier liegt Ratgeber um Ratgeber falsch: die erste Lösung, die du findest, ist, den Bucket öffentlich zu machen, und wenn sie funktioniert, dann weil damit jede Datei in diesem Bucket ebenfalls öffentlich wird. Bei zwei der drei Ursachen ändert sie überhaupt nichts. Bei der übrigen tauscht sie ein kaputtes Bild gegen einen Bucket, aus dem jeder lesen kann, der die Adresse einer Datei hat.

Was bedeutet Supabase "Bucket not found"?

Storage hat nach einem Bucket mit genau dem Namen aus deiner Anfrage gesucht, in dem Projekt, das deine Anfrage erreicht hat, und keinen gefunden, den es dieser Anfrage ausliefern würde.

Der letzte Teil steht da, weil ein Bucket mehr als eine Tür hat und jede Tür die Frage auf ihre eigene Weise stellt. Der Quellcode von Storage zeigt drei davon:

  • Eine öffentliche Dateiadresse, wie getPublicUrl sie baut. Diese Tür zählt nur Buckets, die als öffentlich markiert sind, also ist ein privater Bucket hier "nicht gefunden", obwohl es ihn gibt.
  • Ein Upload. Diese Tür zählt jeden Bucket im Projekt, private eingeschlossen. "Nicht gefunden" heißt hier, dass dieser Name in diesem Projekt wirklich fehlt.
  • Eine Anfrage nach der Dateiliste eines Buckets. Diese Tür sagt nie "Bucket not found". Ein Bucket, den es nicht gibt, antwortet mit einer leeren Liste, derselben Antwort wie ein leerer Bucket, und das sehen wir von außen jedes Mal, wenn unser Scanner fragt.

Die erste Aufgabe ist also herauszufinden, durch welche Tür die gescheiterte Anfrage kam.

Die zwei Zahlen in dieser Meldung widersprechen sich, und das bringt die Fehlerbehandlung durcheinander. Der Body sagt "statusCode": "404", während die Anfrage selbst mit dem HTTP-Status 400 scheitert. Storage schickt diesen Fehler mit einer 400 und behält seine eigene 404 im Body. Die Bibliothek supabase-js reicht beides an deinen Code weiter: error.status ist 400 und error.statusCode ist "404". Code, den dein Builder geschrieben hat, um eine 404 abzufangen, lässt diesen Fehler einfach vorbei.

Das ist die Ursache hinter kaputten Bildern. Die Adresse wurde für einen öffentlichen Bucket gebaut, und der Bucket ist privat.

getPublicUrl fragt Supabase gar nichts. Es setzt die Adresse deines Projekts, den Bucket-Namen und den Dateinamen zu einem Link zusammen, in deiner App, und gibt ihn zurück. Der Hinweis über dieser Funktion in Supabases eigener Client-Bibliothek sagt das in zwei Sätzen:

Diese Funktion prüft nicht, ob der Bucket öffentlich ist. Wird eine öffentliche URL für einen Bucket erzeugt, der nicht öffentlich ist, kannst du die Datei nicht herunterladen.

Später fragt der Browser eines Besuchers nach diesem Link, und Storage sucht den Bucket nur unter den öffentlichen Buckets. Ein privater Bucket fällt bei dieser Suche genauso durch wie ein fehlender, und die Antwort lautet "Bucket not found".

Du erkennst diese Ursache am Link selbst. Eine öffentliche Dateiadresse enthält /storage/v1/object/public/, gefolgt vom Bucket-Namen. Trägt dieser Bucket in Storage → Buckets keine Markierung als öffentlich, konnte sich der Link nie öffnen, egal wie der Name geschrieben ist.

Neue Buckets starten privat, die Einstellung verhält sich also wie vorgesehen. Passiert ist, dass Code für einen öffentlichen Bucket geschrieben und auf einen privaten gerichtet wurde, von dir oder von deinem Builder.

Ein privater Bucket, zwei Arten, nach einer Datei zu fragen. Die öffentliche Adresse wird an der Tür abgewiesen, der signierte Link wird zur selben Datei durchgelassen.

Ursache 2: ein Name, der nicht ganz der Name des Buckets ist

Storage vergleicht den Bucket-Namen Zeichen für Zeichen, also sind Avatars und avatars zwei verschiedene Buckets, und avatar und avatars ebenso.

Im Quellcode von Storage ist die Suche ein schlichter Gleichheitsvergleich auf die id des Buckets. Großbuchstaben zählen, ein fehlender Buchstabe zählt, und ein Bindestrich, wo der Bucket einen Unterstrich hat, zählt. Jeder dieser Fälle kommt als dieselben drei Wörter zurück.

Eine App, die mit einem KI-Werkzeug gebaut wurde, kann hier landen, ohne dass sich irgendwer vertippt hat. Der Code, der eine Datei hochlädt oder anzeigt, entsteht in einem Schritt, und der Bucket, den er nennt, soll in einem anderen angelegt werden. Lief dieser zweite Schritt nie, oder lief er mit einem leicht anderen Namen, fragt der Code nach einem Bucket, den niemand angelegt hat.

Die Prüfung braucht zwei Listen. Öffne Storage → Buckets und notier dir den Namen jedes Buckets genau so, wie er dort steht. Dann sag deinem Builder in einfachen Worten: Liste jeden Storage-Bucket-Namen auf, den diese App benutzt, und zeig mir, wo jeder davon benutzt wird. Jeder Name auf seiner Liste, der auf deiner fehlt, ist der, der scheitert.

Ursache 3: der Bucket liegt in einem anderen Projekt

Deine App spricht mit genau einem Supabase-Projekt, dem in ihrer Supabase-Adresse, und ein Bucket, der in irgendeinem anderen Projekt angelegt wurde, existiert für deine App schlicht nicht.

Am deutlichsten zeigt sich diese Ursache bei einem Upload. Bei einem Upload sucht Storage den Bucket im ganzen Projekt, ohne deine Zugriffsregeln anzuwenden, also ist "Bucket not found" bei einem Upload nie ein Berechtigungsproblem. Wenn der Bucket existiert und deine Regeln die Datei ablehnen, antwortet Storage mit einer anderen Meldung über Row-Level Security. "Bucket not found" bei einem Upload heißt also, dass dieser Name in dem Projekt fehlt, in das deine App schreibt.

Es gibt ganz gewöhnliche Wege zu zwei Projekten: ein Testprojekt neben dem Live-Projekt, eine Kopie der App, die mit einem frischen Projekt verbunden wurde, ein Projekt, das jemand von Hand angelegt hat, um etwas auszuprobieren. Der Bucket landet in dem, das gerade im Dashboard offen war.

Die Prüfung ist ein Vergleich zweier kurzer Zeichenfolgen. Die Supabase-Adresse deiner App sieht aus wie https://<ref>.supabase.co, und der Teil vor .supabase.co ist die Referenz des Projekts. Die Adresse deines Dashboards trägt dieselbe Referenz nach /project/. Weichen die beiden ab, schaust du auf ein Projekt, während deine App mit einem anderen spricht.

Den Bucket gibt es. Er wurde im rechten Projekt angelegt, und jede Anfrage deiner App geht an das linke.

Solltest du den Bucket öffentlich machen, um es zu beheben?

Nur wenn jede Datei im Bucket für jeden gedacht ist, der ihre Adresse hat, und nur bei der ersten Ursache. Bei einem falschen Namen oder einem falschen Projekt ändert der Schalter gar nichts.

Ein öffentlicher Bucket tut eine Sache, und Supabases Dokumentation beschreibt sie in einer Zeile: Jeder, der die Adresse einer Datei besitzt, kann sie öffnen. Eine Anmeldung kommt dabei nicht vor. Supabases eigene Beispiele dafür sind Profilbilder, öffentliche Medien und Inhalte von Blogbeiträgen, und Logos oder Produktfotos gehören in dieselbe Gruppe.

Für Rechnungen, Ausweisscans, Exporte oder alles, was einer Person gehört, ist es die falsche Einstellung. Der Schalter gilt für den ganzen Bucket und für jede Datei, die später dort landet, auch für Dateien aus einer Funktion, die du noch gar nicht gebaut hast.

Dieselbe Abkürzung hat einen Zwilling auf der Seite der Regeln, und den messen wir. Eine Regel auf storage.objects, die nur den Bucket nennt, lässt Downloads für alle funktionieren und gibt außerdem die Liste der Namen im Bucket heraus. Wir haben 8.435 lebende Apps gescannt, die ein Supabase-Projekt nennen. Bei 4.703 davon hat die Bucket-Prüfung eine Antwort bekommen, und 792 haben unsere Listenanfrage mit den Namen dessen beantwortet, was drinlag, ohne dass jemand angemeldet war. Das ist etwa eine von sechs der Apps, die wir fragen konnten. Ist ein Bucket öffentlich und seine Liste ebenfalls offen, dann ist jeder Name auf dieser Liste ein funktionierender Link.

Wie du eine private Datei zeigst, ohne sie öffentlich zu machen

Gib der Seite einen signierten Link: eine Adresse, die für eine Anzahl Sekunden funktioniert, die du festlegst, und danach aufhört zu funktionieren.

Supabases Dokumentation nennt zwei Wege, eine Datei aus einem privaten Bucket zu holen. Der eine ist ein Download, der die Sitzung der angemeldeten Person mitschickt. Der andere ist createSignedUrl, das einen Link baut, "auf den für eine begrenzte Zeit zugegriffen werden kann". Dieser zweite tritt überall an die Stelle von getPublicUrl, wo eine Seite ein Bild zeigt.

Auch ein signierter Link unterliegt deinen Regeln. Bevor Storage irgendetwas signiert, prüft sein Quellcode, ob die anfragende Person diese Datei lesen darf, also braucht ein privater Bucket eine select-Regel auf storage.objects, die festlegt, wer was lesen darf. Der Upload-Fehler erklärt, wie solche Regeln geschrieben werden, auch, warum eine Leseregel, die nur den Bucket nennt, zugleich seine Liste öffnet.

Um das an deinen Builder zu geben, in einfachen Worten: Ersetze für den Bucket hinter dem Fehler "Bucket not found" getPublicUrl durch createSignedUrl, lass den Bucket privat und füge eine Storage-Policy hinzu, mit der jede Person nur die Dateien lesen kann, die sie sehen soll. Lade dann die Seite mit dem kaputten Bild neu.

Was deine Buckets Fremden gerade zeigen

Zwei Ansichten im Dashboard sagen dir, was du eingestellt hast, und eine Prüfung von außen sagt dir, was ein Fremder bekommt.

Storage → Buckets zeigt, welche Buckets öffentlich sind. Frag dich bei jedem öffentlichen, ob jede Datei darin etwas ist, das du einem Fremden zeigen würdest. Storage → Policies zeigt die Regeln. Eine select-Regel, deren einzige Bedingung der Bucket-Name ist, lässt jeden diesen Bucket lesen, seine Dateiliste eingeschlossen.

Unser kostenloser Scan fragt dein Live-Projekt nach der Dateiliste jedes Buckets, nur mit dem Schlüssel, der ohnehin im Code deiner App steht, so wie es ein Fremder tun würde, und sagt dir, welche Buckets mit Namen geantwortet haben. Er liest Namen und lädt nie eine Datei herunter. Er dauert etwa 20 Sekunden und braucht kein Konto: scanne deine App.

Wie deine Dateien dort bleiben, wo du sie abgelegt hast

Nach der heutigen Korrektur können sich noch zwei Dinge bewegen: Jemand legt eine Einstellung um, während er einem anderen Fehler nachgeht, und eine Datei, die jemand gebraucht hat, wird gelöscht.

Reeve Monitor prüft weiter von außen:

  • die vollständige Sicherheitsprüfung, erneut nach Zeitplan, die Prüfung der Bucket-Auflistung eingeschlossen
  • ob deine App erreichbar ist
  • eine Nachricht, wenn sich ein Ergebnis ändert, damit ein Bucket, der über Nacht aufgegangen ist, nicht wartet, bis du hinschaust
  • ein monatlicher Bericht in einfacher Sprache über das, was er gesehen hat

Reeve Care hält eine Kopie von dem, was drinliegt:

  • eine verschlüsselte Kopie deiner Supabase-Datenbank nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos
  • jede Kopie geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle
  • auch deine hochgeladenen Dateien, sobald du einen Storage-Zugang verbindest
  • eine Wiederherstellung per Klick, mit einer Sicherheitskopie des aktuellen Stands vorab
  • alles, was Monitor tut

Was heute zu tun ist

Was zu tun ist

  • Öffne den gescheiterten Link in einem eigenen Tab. Enthält die Adresse /storage/v1/object/public/ und ist der Bucket privat, ist es die erste Ursache.
  • Kopier den Namen des Buckets aus Storage → Buckets und vergleich ihn, Großbuchstaben eingeschlossen, mit dem Namen, den deine App benutzt.
  • Vergleich die Projektreferenz in der Supabase-Adresse deiner App mit der in der Adresse deines Dashboards.
  • Lass einen Bucket privat, außer jede Datei darin ist für jeden gedacht, der ihre Adresse hat, und liefere private Dateien über signierte Links aus.
  • Lies jede select-Regel auf storage.objects. Eine, die nur den Bucket nennt, gibt auch die Dateiliste heraus.

Fang mit der Anfrage an, die gescheitert ist, denn die Tür, durch die sie kam, sagt dir, welche der drei Ursachen du prüfen musst. Die 10-Minuten-Sicherheitscheckliste deckt ab, was eine frisch gestartete App sonst gern offen lässt, und was ein öffentlicher Bucket preisgibt ist die nächste Lektüre, falls sich einer deiner Buckets als öffentlich herausgestellt hat.

FAQ

Warum sagt Supabase, mein Bucket wird nicht gefunden, obwohl ich ihn sehe?

Weil Storage je nach Anfrage auf unterschiedliche Weise nach einem Bucket sucht. Eine öffentliche Dateiadresse, wie getPublicUrl sie baut, wird nur unter öffentlichen Buckets gesucht, also gilt ein privater Bucket, den du im Dashboard siehst, dort als nicht gefunden. Kam der Fehler dagegen von einem Upload, dann passt der Name in deinem Code zu keinem Bucket in dem Projekt, mit dem deine App verbunden ist.

Unterscheidet Supabase bei Bucket-Namen zwischen Groß- und Kleinschreibung?

Ja. Storage vergleicht den Namen Zeichen für Zeichen, also sind Avatars und avatars zwei verschiedene Buckets, und avatar und avatars ebenso. Kopier den Namen aus Storage → Buckets in deinem Dashboard und vergleich ihn mit dem Namen, den deine App benutzt.

Soll ich meinen Bucket öffentlich machen, um "Bucket not found" zu beheben?

Nur wenn jede Datei darin für jeden gedacht ist, der ihre Adresse hat, etwa Profilbilder oder Produktfotos. Öffentlich heißt, dass jeder mit der Adresse einer Datei diese Datei ohne Anmeldung öffnen kann. Den Fehler behebt das nur, wenn ein öffentlicher Link für einen privaten Bucket gebaut wurde; ein falscher Name oder ein falsches Projekt bleibt so oder so kaputt. Für Dateien, die einer Person gehören, lass den Bucket privat und nimm einen signierten Link.

Wie zeige ich eine Datei aus einem privaten Bucket an?

Mit einem signierten Link. createSignedUrl baut eine Adresse, die für eine Anzahl Sekunden funktioniert, die du festlegst, und danach nicht mehr, und sie tritt überall an die Stelle von getPublicUrl, wo eine Seite die Datei zeigt. Wer den Link anfordert, muss die Datei lesen dürfen, also braucht der Bucket eine select-Regel auf storage.objects, die festlegt, wer was lesen darf.

Warum sagt der Fehler 404, wenn die Anfrage mit 400 gescheitert ist?

Supabase Storage schickt diesen Fehler mit dem HTTP-Status 400 und legt seinen eigenen Status, 404, als statusCode in den Body. In supabase-js kommt das als error.status 400 und error.statusCode "404" an, und deshalb lässt Code, der auf eine 404 wartet, diesen Fehler einfach durch.

Geschrieben von

Vlad Tkachenko

Gründer, Reeve

Ich schaue mir den ganzen Tag Apps an, die mit Lovable, Bolt, v0, Cursor und Replit gebaut wurden, und die kurze Liste von Fehlern, die darin immer wieder auftauchen.

Mehr über den Autor

Weiterlesen

Alle Artikel

Sichere deine Supabase-Datenbank vor der nächsten Änderung

Reeve sichert sie verschlüsselt nach Zeitplan und stellt sie für dich wieder her, wenn etwas schiefgeht.

Supabase-Backups ansehen

Automatisierte externe Prüfung, kein vollständiges Audit. Das Fehlen von Funden ist keine Garantie für Sicherheit.