[{"data":1,"prerenderedAt":1333},["ShallowReactive",2],{"blog-de-supabase-function-not-found":3,"blog-index-de":806},{"id":4,"title":5,"body":6,"category":763,"cover":764,"coverAlt":765,"description":766,"draft":767,"extension":768,"faq":769,"image":785,"keywords":786,"meta":795,"navigation":796,"ogTitle":5,"path":797,"published":798,"seo":799,"stem":800,"tldr":801,"updated":798,"__hash__":805},"blog_de\u002Fblog\u002Fsupabase-function-not-found.md","Supabase PGRST202: \"Could not find the function in the schema cache\"",{"type":7,"value":8,"toc":749},"minimark",[9,13,24,31,47,52,55,62,73,99,102,108,112,115,123,134,143,178,207,210,218,224,252,256,263,278,284,295,298,305,319,324,328,343,346,376,396,422,426,429,465,468,482,486,513,516,522,529,533,540,546,557,560,566,569,574,578,595,601,616,622,630,634,637,646,666,675,693,697,742],[10,11,12],"p",{},"Dein Builder hat eine Datenbankfunktion geschrieben, die die Bestellungen eines\nKunden lädt, und die Seite, die sie aufruft, bleibt leer. Die Browserkonsole zeigt\ndas hier:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","{\n  \"code\": \"PGRST202\",\n  \"details\": \"Searched for the function public.get_orders with parameter userId or with a single unnamed json\u002Fjsonb parameter, but no matches were found in the schema cache.\",\n  \"hint\": \"Perhaps you meant to call the function public.get_orders(user_id)\",\n  \"message\": \"Could not find the function public.get_orders(userId) in the schema cache\"\n}\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26,27,30],{},"Supabase \"Could not find the function in the schema cache\" heißt, dass PostgREST\nkeine Funktion mit diesem Namen hat, die genau die Argumente annimmt, die deine App\ngeschickt hat. PostgREST ist der Teil von Supabase, der die Aufrufe\n",[21,28,29],{},"supabase.rpc()"," deiner App beantwortet, und es führt eine eigene Liste aller\nFunktionen, die es aufrufen kann: den Schema-Cache.",[10,32,33,34,38,39,42,43,46],{},"Hier liegt der Teil, den die meisten Antworten falsch machen: ",[35,36,37],"strong",{},"Sie sagen dir, du\nsollst den Schema-Cache neu laden."," Bei Supabase aktualisiert sich diese Liste von\nselbst, sobald eine Funktion angelegt oder geändert wird. Die Meldung hat dir schon\ngesagt, was nicht stimmt. ",[21,40,41],{},"userId"," in den Klammern ist das, was deine App\ngeschickt hat. ",[21,44,45],{},"user_id"," im Hinweis ist das, was die Funktion erwartet.",[48,49,51],"h2",{"id":50},"was-bedeutet-could-not-find-the-function-in-the-schema-cache","Was bedeutet \"Could not find the function in the schema cache\"?",[10,53,54],{},"Keine Funktion in dem Schema, das PostgREST durchsucht hat, hat diesen Namen\nzusammen mit genau diesen Argumentnamen.",[10,56,57,58,61],{},"Stell dir jede Datenbankfunktion als gedrucktes Formular vor, das hinter einem\nSchalter an der Wand hängt: oben ihr Name, darunter ein beschriftetes Feld für\njedes Argument. Wenn deine App ",[21,59,60],{},"supabase.rpc('get_orders', { userId: id })","\naufruft, reicht sie eine ausgefüllte Kopie über den Schalter. PostgREST sucht ein\nFormular an der Wand mit demselben Namen und denselben Feldbeschriftungen. Hat\nkeines sie, wird die Kopie am Schalter zurückgegeben, und die Meldung liest dir die\nBeschriftungen vor, die du ausgefüllt hast.",[10,63,64,65,72],{},"Vier Dinge stehen fest im\n",[66,67,71],"a",{"href":68,"rel":69},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FError.hs",[70],"nofollow","eigenen Code von PostgREST",":",[74,75,76,84,90,96],"ul",{},[77,78,79,80,83],"li",{},"der Code ist ",[21,81,82],{},"PGRST202"," und der Status HTTP 404, der Status einer Seite, die es\nnicht gibt",[77,85,86,87],{},"die Klammern nennen die Argumentnamen, die deine App geschickt hat. Hat sie\nkeine geschickt, steht an ihrer Stelle ",[21,88,89],{},"without parameters",[77,91,92,95],{},[21,93,94],{},"public."," vor dem Namen ist das Schema, das PostgREST durchsucht hat",[77,97,98],{},"der Hinweis nennt, wenn es einen gibt, die ähnlichste Funktion, die PostgREST\nkennt, mit deren eigenen Argumentnamen",[10,100,101],{},"Vergleich die Klammern mit dem Hinweis, bevor du irgendetwas anderes tust.",[103,104],"diagram",{"alt":105,"caption":106,"src":107},"Eine ausgefüllte Kopie des Formulars get_orders neben dem Formular get_orders an der Wand. Das Feld limit auf der Kopie ist mit dem Feld limit an der Wand verbunden und abgehakt. Das Feld userId auf der Kopie läuft in Bernstein zu einem Ungleichzeichen neben user_id und fällt zu einer Plakette mit PGRST202 und 404.","PostgREST ordnet einen Aufruf über den Namen der Funktion und jeden Argumentnamen zu. userId und user_id sind zwei verschiedene Beschriftungen, also passt kein Formular an der Wand.","\u002Fblog\u002Fsupabase-function-not-found\u002Fargument-names-must-match-1600x680.png",[48,109,111],{"id":110},"ursache-1-die-argumentnamen-stimmen-nicht-überein","Ursache 1: Die Argumentnamen stimmen nicht überein",[10,113,114],{},"PostgREST wählt eine Funktion über ihren Namen und ihre Argumentnamen zusammen\naus. Eine Funktion, die mit den falschen Namen aufgerufen wird, ist für PostgREST\nalso eine Funktion, die es nicht gibt.",[10,116,117,118,72],{},"Die Regeln, aus der Suche im\n",[66,119,122],{"href":120,"rel":121},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FPlan.hs",[70],"Planer von PostgREST",[74,124,125,128,131],{},[77,126,127],{},"jedes Argument ohne Standardwert muss geschickt werden, unter seinem genauen\nNamen",[77,129,130],{},"ein Argument mit Standardwert darf fehlen",[77,132,133],{},"ein Name, den die Funktion nicht deklariert, schließt diese Funktion aus, auch\nwenn alle anderen Namen passen",[10,135,136,137,139,140,142],{},"Ein Name kann auf drei Arten falsch sein, die leicht zu übersehen sind. Die erste\nist JavaScript, das auf SQL trifft: Deine App schreibt ",[21,138,41],{},", und die Funktion\ndeklariert ",[21,141,45],{},".",[10,144,145,146,149,150,152,153,156,157,162,163,166,167,170,171,166,174,177],{},"Die zweite ist ein Präfix. Manche Funktionen nennen ihre Argumente ",[21,147,148],{},"p_user_id",",\ndamit man sie nicht mit einer Spalte namens ",[21,151,45],{}," verwechselt, und dann muss\nauch der Aufruf das ",[21,154,155],{},"p_"," tragen. In einer\n",[66,158,161],{"href":159,"rel":160},"https:\u002F\u002Fgithub.com\u002Forgs\u002Fsupabase\u002Fdiscussions\u002F28379",[70],"Diskussion bei Supabase","\nschickte der Aufruf ",[21,164,165],{},"id",", ",[21,168,169],{},"nombre"," und drei weitere, die Funktion deklarierte\n",[21,172,173],{},"p_id",[21,175,176],{},"p_nombre"," und den Rest, und der Hinweis druckte jeden der richtigen Namen.",[10,179,180,181,184,185,188,189,194,195,197,198,201,202,206],{},"Die dritte ist die Regel, die auch Spalten umbenennt. Ein Name, der in SQL ohne\ndoppelte Anführungszeichen geschrieben wird, wird in Kleinbuchstaben umgewandelt,\nalso speichert ",[21,182,183],{},"create function get_orders(userId uuid)"," das Argument als ",[21,186,187],{},"userid",".\nEin\n",[66,190,193],{"href":191,"rel":192},"https:\u002F\u002Fcommunity.flutterflow.io\u002Fask-the-community\u002Fpost\u002Fcustom-action-calling-a-supabase-function---fails-with-a-postgres-IsfG19NQeLRmfRP",[70],"Nutzer von FlutterFlow","\nist genau darauf gestoßen: Der Aufruf schickte ",[21,196,41],{},", und der Hinweis antwortete\n",[21,199,200],{},"(userid)",". ",[66,203,205],{"href":204},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Die Spaltenversion dieses Fehlers","\nhat eine Tabelle dazu, was jede Schreibweise anlegt.",[10,208,209],{},"Um die Namen zu sehen, die die Datenbank gespeichert hat, führ das im SQL Editor\naus:",[14,211,216],{"className":212,"code":214,"language":215,"meta":23},[213],"language-sql","select p.proname, pg_get_function_arguments(p.oid)\nfrom pg_proc p\njoin pg_namespace n on n.oid = p.pronamespace\nwhere n.nspname = 'public' and p.proname = 'get_orders';\n","sql",[21,217,214],{"__ignoreMap":23},[10,219,220,223],{},[21,221,222],{},"pg_get_function_arguments"," gibt die Argumente so aus, wie sie deklariert wurden,\nmit ihren Standardwerten, und zeigt damit auch, welche du weglassen darfst.",[10,225,226,227,230,231,233,234,237,238,241,242,247,248,251],{},"Die sicherere Lösung liegt in der App, weil sie an der Datenbank nichts ändert.\nBitte deinen Builder, die Funktion mit ihren gespeicherten Namen aufzurufen:\n\"",[21,228,229],{},"get_orders"," nimmt ",[21,232,45],{},"; übergib ",[21,235,236],{},"{ user_id: … }"," in jedem Aufruf von\n",[21,239,240],{},".rpc()"," an diese Funktion\". Das Argument umzubenennen ist schwieriger, als es\naussieht. Die\n",[66,243,246],{"href":244,"rel":245},"https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002Fcurrent\u002Fsql-createfunction.html",[70],"Dokumentation von Postgres","\nsagt über ",[21,249,250],{},"CREATE OR REPLACE FUNCTION",": \"You cannot change the name already\nassigned to any input parameter\". Die Funktion muss gelöscht und neu angelegt\nwerden, und jede andere Seite, die sie unter dem alten Namen aufruft, scheitert\ndanach auf dieselbe Weise.",[48,253,255],{"id":254},"ursache-2-der-wert-war-undefined-also-wurde-der-name-nie-geschickt","Ursache 2: Der Wert war undefined, also wurde der Name nie geschickt",[10,257,258,259,262],{},"Ein Argument mit dem Wert ",[21,260,261],{},"undefined"," kommt nie bei PostgREST an, und die Funktion\nwird dann ohne dieses Argument gesucht.",[10,264,265,266,268,269,277],{},"supabase-js schickt deine Argumente als JSON, und JSON kennt kein ",[21,267,261],{},". Die\n",[66,270,273,274],{"href":271,"rel":272},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FJSON\u002Fstringify",[70],"MDN-Referenz zu ",[21,275,276],{},"JSON.stringify","\nsagt, solche Werte \"are either omitted (when found in an object) or changed to\nnull (when found in an array)\". Dieser Aufruf, gemacht, bevor der angemeldete\nNutzer geladen ist:",[14,279,282],{"className":280,"code":281,"language":19},[17],"await supabase.rpc('get_orders', { user_id: user?.id })\n",[21,283,281],{"__ignoreMap":23},[10,285,286,287,290,291,294],{},"schickt also ",[21,288,289],{},"{}",", und die Antwort lautet\n",[21,292,293],{},"Could not find the function public.get_orders without parameters in the schema cache",".\nBei zwei Argumenten, von denen eines undefined ist, nennen die Klammern nur das,\ndas angekommen ist.",[10,296,297],{},"Der Name in deinem Code stimmt, und deshalb findet man den Fehler nicht, indem man\nden Code liest. Die Meldung zeigt ihn: Die Klammern sind leer oder einen Namen\nkürzer als das, was der Code übergibt.",[10,299,300,301,304],{},"Die Lösung ist, den Aufruf erst zu machen, wenn der Wert da ist. Wenn die Funktion\nmit einem fehlenden Wert umgehen kann, übergib bewusst ",[21,302,303],{},"null",", das JSON behält.",[10,306,307,308,311,312,314,315,142],{},"Ein Filter macht mit demselben Wert das Gegenteil. ",[21,309,310],{},".eq('user_id', user?.id)","\nsetzt ihn als das Wort ",[21,313,261],{}," in die Anfrage, und eine uuid-Spalte antwortet\nmit ",[66,316,318],{"href":317},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","invalid input syntax for type uuid",[103,320],{"alt":321,"caption":322,"src":323},"Eine ausgefüllte Kopie von get_orders, in der user_id in Bernstein undefined enthält und limit 10. Ein Pfeil mit der Aufschrift JSON.stringify führt zur Kopie, die tatsächlich geschickt wird: Dort ist das Feld user_id ein gestrichelter leerer Platz, und nur limit 10 bleibt. Ein zweiter Pfeil führt zu einer Plakette mit PGRST202 und 404.","JSON lässt einen Wert weg, der undefined ist. Das Argument verschwindet unterwegs, und PostgREST sucht eine Funktion ohne es.","\u002Fblog\u002Fsupabase-function-not-found\u002Fundefined-is-never-sent-1600x560.png",[48,325,327],{"id":326},"ursache-3-die-funktion-liegt-in-einem-anderen-schema","Ursache 3: Die Funktion liegt in einem anderen Schema",[10,329,330,332,333,336,337,342],{},[21,331,29],{}," sucht im Schema ",[21,334,335],{},"public",", dem, das die Meldung nennt, solange du\nnichts anderes sagst. Eine Funktion, die woanders angelegt wurde, steht gar nicht\nauf der Liste von PostgREST:\n",[66,338,341],{"href":339,"rel":340},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FSchemaCache.hs",[70],"Es lädt Funktionen","\nnur aus den Schemas, die dein Projekt über seine API freigibt.",[10,344,345],{},"Das zeigt sich auf zwei Arten:",[74,347,348,363],{},[77,349,350,351,354,355,358,359,362],{},"die Funktion wurde in einem eigenen Schema angelegt, etwa ",[21,352,353],{},"private"," oder\n",[21,356,357],{},"billing",", und wird mit einem schlichten ",[21,360,361],{},".rpc('get_orders')"," aufgerufen",[77,364,365,366,369,370,372,373],{},"das Schema steht im Namen, als ",[21,367,368],{},".rpc('billing.get_orders')",". PostgREST liest\ndie ganze Zeichenkette als einen Namen und sucht ihn in ",[21,371,335],{},", also sagt die\nMeldung ",[21,374,375],{},"public.billing.get_orders",[10,377,378,379,382,383,388,389,166,392,395],{},"Eine Funktion in einem anderen Schema rufst du mit\n",[21,380,381],{},".schema('billing').rpc('get_orders', …)"," auf, und dieses Schema muss in den\nAPI-Einstellungen des Projekts unter Exposed schemas stehen, wie\n",[66,384,387],{"href":385,"rel":386},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fapi\u002Fusing-custom-schemas",[70],"Supabases Anleitung zu eigenen Schemas","\nzeigt. Bis dahin ändert sich die Antwort zu ",[21,390,391],{},"PGRST106",[21,393,394],{},"Invalid schema: billing",",\nmit einem Hinweis, der die freigegebenen Schemas aufzählt.",[10,397,398,399,402,403,406,407,411,412,416,417,421],{},"Ein Schema so freizugeben, wie diese Anleitung es tut, öffnet jede Tabelle darin.\nDie Anleitung gibt ",[21,400,401],{},"anon"," und ",[21,404,405],{},"authenticated"," Zugriff auf jede Tabelle im neuen\nSchema, und von da an entscheiden allein deine\n",[66,408,410],{"href":409},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security","-Regeln, was ein\nBesucher dort lesen kann.\n",[66,413,415],{"href":414},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Die Tabellenversion dieses Fehlers"," hat\ndie Abfrage, die vor der Freigabe zeigt, bei welchen Tabellen eines Schemas\ndiese Regeln ausgeschaltet sind. Manche Funktionen liegen in einem privaten Schema, damit\nniemand sie von außen aufrufen kann: Unsere\n",[66,418,420],{"href":419},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","Anleitung zu unendlicher Rekursion in einer Policy","\nlegt eine genau aus diesem Grund dorthin. Ein Aufruf einer solchen Funktion aus dem\nBrowser bekommt PGRST202 mit Absicht, und ihr Schema sollte nicht freigegeben\nwerden.",[48,423,425],{"id":424},"ursache-4-der-name-der-funktion-selbst-oder-gar-keine-funktion","Ursache 4: Der Name der Funktion selbst, oder gar keine Funktion",[10,427,428],{},"PostgREST schlägt den Namen genau nach, Buchstabe für Buchstabe, mit Groß- und\nKleinschreibung.",[74,430,431,441,451],{},[77,432,433,434,437,438,440],{},"ein Tippfehler, oder ",[21,435,436],{},"getOrders"," im Aufruf gegen ",[21,439,229],{}," in der Datenbank",[77,442,443,444,446,447,450],{},"eine Funktion, die ohne doppelte Anführungszeichen als ",[21,445,436],{}," angelegt\nwurde und nach derselben Regel wie ihre Argumente als ",[21,448,449],{},"getorders"," gespeichert ist",[77,452,453,454,457,458,460,461,464],{},"eine Prozedur. PostgREST führt nur Funktionen, also legt ",[21,455,456],{},"create procedure","\netwas an, das ",[21,459,240],{}," nicht erreicht, und dasselbe gilt für eine Funktion mit\n",[21,462,463],{},"returns trigger",", die von einem Trigger ausgeführt wird und nie von deiner App",[10,466,467],{},"Auch hier hilft der Hinweis. Gibt es keine Funktion mit diesem Namen, schlägt\nPostgREST den nächstliegenden Namen vor, den es hat, wenn einer nah genug ist.",[10,469,470,471,476,477,481],{},"Oder die Funktion wurde in der Datenbank, die deine App aufruft, nie angelegt.\nWenn du mit Lovable baust, such im Chat nach SQL, das du freigeben solltest. Die\n",[66,472,475],{"href":473,"rel":474},"https:\u002F\u002Fdocs.lovable.dev\u002Fintegrations\u002Fsupabase",[70],"Supabase-Dokumentation von Lovable","\nsagt, Lovable \"writes the SQL, shows it to you, and asks for your approval in the\nproject chat before running it\". Bis du freigibst, existiert die Funktion nur im\nCode, der sie aufruft. Hat jemand sie von Hand angelegt, prüf, dass sie in dem\nProjekt gelandet ist, mit dem deine App spricht:\n",[66,478,480],{"href":479},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Ein Branch ist ein eigenes Projekt"," mit\neigener Datenbank.",[48,483,485],{"id":484},"ursache-5-der-cache-ist-wirklich-veraltet","Ursache 5: Der Cache ist wirklich veraltet",[10,487,488,489,492,493,402,496,499,500,503,504,507,508,142],{},"Bei Supabase ist das der seltene Fall. Jede Supabase-Datenbank hat einen Event\nTrigger, ",[21,490,491],{},"pgrst_ddl_watch",", der nach jedem ",[21,494,495],{},"CREATE FUNCTION",[21,497,498],{},"ALTER FUNCTION","\ndie Nachricht ",[21,501,502],{},"NOTIFY pgrst, 'reload schema'"," schickt, und ein zweiter,\n",[21,505,506],{},"pgrst_drop_watch",", schickt sie, nachdem eine Funktion gelöscht wurde. Beide stehen\nin\n",[66,509,512],{"href":510,"rel":511},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fpostgres\u002Fblob\u002Fdevelop\u002Fmigrations\u002Fschema-17.sql",[70],"Supabases Datenbank-Setup",[10,514,515],{},"Kommt diese Nachricht nicht an, lade die Liste im SQL Editor von Hand neu:",[14,517,520],{"className":518,"code":519,"language":215,"meta":23},[213],"NOTIFY pgrst, 'reload schema';\n",[21,521,519],{"__ignoreMap":23},[10,523,524,525,528],{},"Ändert das nichts, behandelt\n",[66,526,527],{"href":204},"die Spaltenversion dieses Fehlers"," die\nnächsten zwei Schritte, die festhängende Benachrichtigungswarteschlange und den\nNeustart des Projekts. Beide funktionieren für Funktionen genauso.",[48,530,532],{"id":531},"wenn-zwei-funktionen-einen-namen-teilen","Wenn zwei Funktionen einen Namen teilen",[10,534,535,536,539],{},"PostgREST rät nicht zwischen ihnen. Wenn zwei Funktionen denselben Namen haben und\nbeide die Argumente annehmen, die deine App geschickt hat, scheitert der Aufruf mit\n",[21,537,538],{},"PGRST203"," und HTTP 300:",[14,541,544],{"className":542,"code":543,"language":19},[17],"Could not choose the best candidate function between: public.get_orders(user_id => uuid), public.get_orders(user_id => text)\n",[21,545,543],{"__ignoreMap":23},[10,547,548,549,551,552,556],{},"Eine Reparatur von PGRST202 ist ein Weg hierher. Dein Builder ändert den Typ eines\nArguments mit ",[21,550,250],{},", und Postgres ersetzt gar nichts. Seine\n",[66,553,555],{"href":244,"rel":554},[70],"Dokumentation","\nsagt, dass sich die Argumenttypen so nicht ändern lassen: \"if you tried, you would\nactually be creating a new, distinct function\". Jetzt gibt es beide Versionen\nnebeneinander.",[10,558,559],{},"Der Hinweis von PostgREST lautet hier \"Try renaming the parameters or the function\nitself in the database so function overloading can be resolved\". Die schlichtere\nLösung ist, die Version zu löschen, die du nicht willst, und dabei ihren\nArgumenttyp zu nennen, damit Postgres weiß, welche gemeint ist:",[14,561,564],{"className":562,"code":563,"language":215,"meta":23},[213],"drop function public.get_orders(text);\n",[21,565,563],{"__ignoreMap":23},[10,567,568],{},"Prüf, welche Version deine App aufruft, bevor du eine der beiden löschst.",[103,570],{"alt":571,"caption":572,"src":573},"Eine ausgefüllte Kopie von get_orders mit user_id und zwei Formulare get_orders an der Wand, eines, dessen Feld user_id uuid annimmt, und eines, dessen Feld text annimmt. Gestrichelte bernsteinfarbene Linien laufen von der Kopie zu beiden Formularen, und die Kopie fällt zu einer Plakette mit PGRST203 und 300.","Wer den Typ eines Arguments mit CREATE OR REPLACE ändert, legt eine zweite Funktion mit demselben Namen an. Ein Aufruf, der zu beiden passt, wird abgelehnt.","\u002Fblog\u002Fsupabase-function-not-found\u002Ftwo-functions-one-name-1600x700.png",[48,575,577],{"id":576},"eine-supabase-funktion-richtig-aufrufen","Eine Supabase-Funktion richtig aufrufen",[10,579,580,581,586,587,590,591,594],{},"Übergib ein Objekt, dessen Schlüssel die Argumentnamen der Funktion sind, so\ngeschrieben, wie die Datenbank sie gespeichert hat. In\n",[66,582,585],{"href":583,"rel":584},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fdatabase\u002Ffunctions",[70],"Supabases Anleitung zu Datenbankfunktionen","\nwird eine Funktion, die als ",[21,588,589],{},"add_planet(name text)"," deklariert ist, mit\n",[21,592,593],{},"supabase.rpc('add_planet', { name: 'Jakku' })"," aufgerufen.",[10,596,597,598,600],{},"Sobald deine App die Funktion aufrufen kann, kann es jeder andere auch. Dieselbe\nAnleitung sagt es klar: \"By default, any role can run a database function.\" Dazu\ngehört ",[21,599,401],{},", die Rolle hinter jeder Anfrage eines Besuchers, der nicht\nangemeldet ist. Eine Funktion, die deine App aus dem Browser aufruft, kann jeder\naufrufen, der deinen öffentlichen Schlüssel hat, mit beliebigen Argumenten.",[10,602,603,604,402,606,608,609,612,613,615],{},"Für eine Funktion, die nur angemeldete Nutzer ausführen sollen, folg der\nAnleitung: Nimm ",[21,605,335],{},[21,607,401],{}," das Recht ",[21,610,611],{},"execute"," weg und gib es\n",[21,614,405],{}," zurück.",[14,617,620],{"className":618,"code":619,"language":215,"meta":23},[213],"revoke execute on function public.get_orders from public, anon;\ngrant execute on function public.get_orders to authenticated;\n",[21,621,619],{"__ignoreMap":23},[10,623,624,625,629],{},"Deine Tabellen sind die andere Hälfte dessen, was dieser öffentliche Schlüssel\nerreicht. Unser ",[66,626,628],{"href":627},"\u002Fsecurity-scanner","kostenloser Scan"," prüft von außen, ob sie\njedem, der ihn hat, Zeilen herausgeben, und er braucht kein Konto.",[48,631,633],{"id":632},"eine-funktion-ändern-von-der-deine-app-abhängt","Eine Funktion ändern, von der deine App abhängt",[10,635,636],{},"Behalte eine Kopie der Datenbank von vor der Änderung, und erfahre es, wenn sich\netwas ändert, das deine App preisgibt.",[10,638,639],{},[35,640,641,645],{},[66,642,644],{"href":643},"\u002Fsupabase-backups","Reeve Care"," bewahrt eine Kopie deiner Supabase-Datenbank auf:",[74,647,648,651,654,657,660,663],{},[77,649,650],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[77,652,653],{},"die Kopie von vor deiner Änderung enthält deine Funktionen so, wie sie damals definiert waren, neben deinen Tabellen und Zeilen",[77,655,656],{},"jede Kopie wird geprüft, bevor sie zählt, indem die Zeilen in jeder Tabelle gezählt werden",[77,658,659],{},"auch deine hochgeladenen Dateien, sobald du eine Storage-Zugangsberechtigung verbindest",[77,661,662],{},"Wiederherstellung mit einem Klick, vorher wird eine Sicherheitskopie des aktuellen Stands angelegt",[77,664,665],{},"alles, was Monitor macht",[10,667,668],{},[35,669,670,674],{},[66,671,673],{"href":672},"\u002Fwebsite-monitoring","Reeve Monitor"," prüft weiter von außen:",[74,676,677,680,683,690],{},[77,678,679],{},"ob deine App erreichbar ist, jede Minute geprüft",[77,681,682],{},"der vollständige Sicherheitscheck jede Stunde, für bis zu drei Apps",[77,684,685,686,689],{},"eine Nachricht, wenn sich ein Ergebnis ",[35,687,688],{},"ändert",", sodass ein Deploy, der ändert, was deine App preisgibt, dich erreicht, ohne dass du nachsehen musst",[77,691,692],{},"ein monatlicher Bericht in klarer Sprache über das, was er gesehen hat",[48,694,696],{"id":695},"was-du-jetzt-tun-solltest","Was du jetzt tun solltest",[698,699,700],"key-takeaways",{},[74,701,702,705,711,717,724,727,734],{},[77,703,704],{},"Lies die Meldung: Die Namen in Klammern hat deine App geschickt, und der Hinweis nennt, was die Datenbank hat.",[77,706,707,708,710],{},"Vergleich die Argumentnamen Buchstabe für Buchstabe, samt einem Präfix wie ",[21,709,155],{},". Ein Name, der in SQL ohne Anführungszeichen geschrieben wurde, wird kleingeschrieben gespeichert.",[77,712,713,714,716],{},"Sind die Klammern leer oder einen Namen zu kurz, such nach einem Wert, der beim Aufruf ",[21,715,261],{}," war.",[77,718,719,720,723],{},"Prüf das Schema in der Meldung. Eine Funktion in einem anderen Schema braucht ",[21,721,722],{},".schema('name').rpc(…)"," und ein freigegebenes Schema, und wer eines freigibt, macht auch seine Tabellen erreichbar.",[77,725,726],{},"Teilen sich zwei Funktionen den Namen, lösch die Version, die deine App nicht aufruft.",[77,728,729,730,733],{},"Führ ",[21,731,732],{},"NOTIFY pgrst, 'reload schema';"," erst aus, wenn die Namen passen.",[77,735,736,737,608,739,741],{},"Nimm ",[21,738,401],{},[21,740,611],{}," bei jeder Funktion weg, die ein nicht angemeldeter Besucher nie ausführen soll.",[10,743,744,745,748],{},"Fang bei den Klammern an, denn sie enthalten genau das, was deine App geschickt\nhat. Bevor du eine Funktion löschst oder ersetzt, von der deine App abhängt,\n",[66,746,747],{"href":643},"behalte eine Kopie der Datenbank"," von vor der Änderung.",{"title":23,"searchDepth":750,"depth":750,"links":751},3,[752,754,755,756,757,758,759,760,761,762],{"id":50,"depth":753,"text":51},2,{"id":110,"depth":753,"text":111},{"id":254,"depth":753,"text":255},{"id":326,"depth":753,"text":327},{"id":424,"depth":753,"text":425},{"id":484,"depth":753,"text":485},{"id":531,"depth":753,"text":532},{"id":576,"depth":753,"text":577},{"id":632,"depth":753,"text":633},{"id":695,"depth":753,"text":696},"Sicherheitsgrundlagen","\u002Fblog\u002Fsupabase-function-not-found\u002Fcover-1200x630.png","Ein an die Wand gehängtes Formular mit beschrifteten Feldern, davor eine ausgefüllte Kopie mit einem bernsteinfarben markierten Feld.","Supabase \"Could not find the function in the schema cache\" nennt die Argumente, die deine App geschickt hat. Vergleich sie mit der Funktion.",false,"md",[770,773,776,779,782],{"q":771,"a":772},"Was bedeutet PGRST202?","PGRST202 ist der Code, den PostgREST, der Teil von Supabase, der Aufrufe von supabase.rpc() beantwortet, zurückgibt, wenn keine Funktion zu einem Aufruf passt. Er kommt mit HTTP 404 und der Meldung \"Could not find the function public.name(arguments) in the schema cache\". Die Namen in Klammern sind die Argumente, die deine App geschickt hat, und public ist das Schema, in dem gesucht wurde.",{"q":774,"a":775},"Die Funktion existiert. Warum meldet mein RPC-Aufruf, dass sie fehlt?","PostgREST erkennt eine Funktion an ihrem Namen und ihren Argumentnamen zusammen. Schick jedes Argument ohne Standardwert, unter genau dem Namen, den die Datenbank gespeichert hat, und nichts, was die Funktion nicht deklariert. Ein Name, der in SQL ohne doppelte Anführungszeichen geschrieben wurde, wird kleingeschrieben gespeichert, aus userId in einem create function wird also userid.",{"q":777,"a":778},"Warum steht in der Meldung \"without parameters\"?","Deine App hat überhaupt keine Argumente geschickt. Mit supabase-js ist der übliche Grund ein Wert, der beim Aufruf undefined war: Die Argumente reisen als JSON, und JSON lässt undefined-Werte weg, also kommt { user_id: undefined } als {} an. Ruf die Funktion erst auf, wenn der Wert da ist, oder übergib null, wenn die Funktion mit einem fehlenden Wert umgehen kann.",{"q":780,"a":781},"Muss die Funktion im Schema public liegen?","supabase.rpc() sucht in public, solange du mit .schema('name') kein anderes Schema wählst, und dieses Schema muss in den API-Einstellungen des Projekts unter Exposed schemas stehen. Ein freigegebenes Schema macht seinen Inhalt über die API erreichbar, also lohnt es sich, das bewusst zu entscheiden.",{"q":783,"a":784},"Wie lade ich den Supabase-Schema-Cache neu?","Führ NOTIFY pgrst, 'reload schema'; im SQL Editor aus. Supabase schickt diese Nachricht schon von selbst, sobald eine Funktion angelegt, geändert oder gelöscht wird, Neuladen hilft also nur, wenn die Nachricht nicht angekommen ist. Prüf zuerst die Namen.","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",[787,788,789,790,791,792,793,794],"could not find the function in the schema cache","pgrst202","supabase rpc funktion nicht gefunden","supabase rpc 404","supabase funktion parameter stimmen nicht","could not find the function without parameters in the schema cache","pgrst203","could not choose the best candidate function",{},true,"\u002Fblog\u002Fsupabase-function-not-found","2026-10-22",{"title":5,"description":766},"blog\u002Fsupabase-function-not-found",[802,803,804],"Supabase \"Could not find the function in the schema cache\" (PGRST202) heißt: Keine Funktion hat diesen Namen und nimmt genau die Argumentnamen an, die deine App geschickt hat. Die Namen in Klammern in der Meldung sind die, die deine App geschickt hat.","Prüf zuerst die Argumentnamen: userId an eine Funktion geschickt, die user_id deklariert, ein fehlendes Präfix p_ oder ein Wert, der undefined war und darum nie geschickt wurde.","Supabase aktualisiert seine Liste der Funktionen von selbst, sobald eine angelegt, geändert oder gelöscht wird. Prüf also die Namen und das Schema, bevor du irgendetwas neu lädst.","sVB8GYL1F1MCWAbmpN7-pCcFPE5sRWfapigp5dsrltY",[807,813,819,825,831,837,843,849,855,861,867,874,880,886,892,898,903,909,914,915,920,926,932,938,944,950,956,962,968,974,980,986,992,997,1003,1009,1015,1021,1027,1033,1039,1045,1051,1057,1063,1069,1074,1080,1086,1092,1098,1104,1110,1116,1122,1128,1134,1140,1146,1152,1158,1164,1169,1175,1181,1187,1193,1199,1205,1211,1217,1223,1229,1235,1241,1247,1253,1259,1264,1270,1276,1282,1288,1294,1299,1305,1311,1317,1322,1328],{"path":808,"title":809,"description":810,"published":811,"category":763,"image":812,"draft":767},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\" erklärt","Supabase \"max client connections reached\": Der Pooler hat keinen Platz für noch einen Client. Der Port in deinem Connection String setzt das Limit.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":814,"title":815,"description":816,"published":817,"category":763,"image":818,"draft":767},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Supabase-Fehler: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\" heißt: Google-Login ist in deinem Supabase-Projekt aus. Die Lösung, und was bei redirect_uri_mismatch hilft.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":820,"title":821,"description":822,"published":823,"category":763,"image":824,"draft":767},"\u002Fblog\u002Fviolates-foreign-key-constraint","Supabase-Fehler \"violates foreign key constraint\" beim Einfügen","Supabase \"insert or update on table violates foreign key constraint\": Deine Zeile zeigt auf eine, die es nicht gibt. Welche, warum, und die Lösung.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":826,"title":827,"description":828,"published":829,"category":763,"image":830,"draft":767},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Supabase-Fehler \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": Eine Pflichtspalte kam leer an. Woher die Null kommt, und die Lösung.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":832,"title":833,"description":834,"published":835,"category":763,"image":836,"draft":767},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": wo die Sitzung geblieben ist","\"Auth session missing!\" heißt: supabase-js fand keine angemeldete Sitzung und fragte Supabase gar nicht erst. Wo die Sitzung blieb, und die Lösung je Fall.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":838,"title":839,"description":840,"published":841,"category":763,"image":842,"draft":767},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","Supabase \"invalid claim: missing sub claim\": niemand ist angemeldet","\"invalid claim: missing sub claim\" heißt: Supabase Auth bekam ein echtes Token ohne Nutzer darin, deinen Projektschlüssel statt einer Sitzung.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":844,"title":845,"description":846,"published":847,"category":763,"image":848,"draft":767},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": der echte Grund","\"Failed to send a request to the Edge Function\" heißt: Der Browser hat keine lesbare Antwort bekommen. Seine Konsole sagt, warum, und ob deine Funktion lief.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":850,"title":851,"description":852,"published":853,"category":763,"image":854,"draft":767},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Warum Supabase-E-Mail-Links auf localhost:3000 weiterleiten","Leitet Supabase auf localhost:3000 um, ist die Site URL unverändert, oder deine Adresse fehlt in Redirect URLs. Die Lösung und der Platzhalter, den du meidest.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":856,"title":857,"description":858,"published":859,"category":763,"image":860,"draft":767},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" bei einem neuen Link","Bei einem Link von vor einer Minute heißt Supabases \"Email link is invalid or has expired\" meist: Ein Mailfilter hat ihn zuerst benutzt. Prüfen und beheben.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":862,"title":863,"description":864,"published":865,"category":763,"image":866,"draft":767},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\" erklärt","Supabase \"canceling statement due to statement timeout\": Eine Abfrage lief länger als ihre Rolle darf, 3 Sekunden für Besucher. Prüf zuerst die RLS-Regel.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":868,"title":869,"description":870,"published":871,"category":872,"image":873,"draft":767},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" in Supabase und was mitgelöscht wird","\"Database error deleting user\" in Supabase heißt: Deine Datenbank hat das Löschen abgelehnt. Der Grund steht im Log, die Lösung entscheidet, was mitgeht.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":875,"title":876,"description":877,"published":878,"category":763,"image":879,"draft":767},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" bei Supabase","Ein Stripe-Webhook in einer Supabase Edge Function meldet \"No signatures found matching the expected signature\"? Zwei Ursachen. Prüfe weiter.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":881,"title":882,"description":883,"published":884,"category":763,"image":885,"draft":767},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" in Supabase: die drei Ursachen","Supabase sagt \"Invalid login credentials\" bei falschem Passwort, unbekannter E-Mail und Google-Konto. So erkennst du, welcher Fall es ist.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":887,"title":888,"description":889,"published":890,"category":763,"image":891,"draft":767},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": der echte Fehler","\"Edge Function returned a non-2xx status code\" heißt: Deine Supabase-Funktion hat mit einem Fehler geantwortet. So liest du den echten.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":893,"title":894,"description":895,"published":896,"category":763,"image":897,"draft":767},"\u002Fblog\u002Fcertificate-not-trusted","Zertifikat nicht vertrauenswürdig: drei Ursachen außer Ablauf","Zertifikat nicht vertrauenswürdig, obwohl das Datum stimmt? Es nennt eine andere Adresse, hat sich selbst signiert oder seiner Kette fehlt ein Glied.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":317,"title":899,"description":900,"published":901,"category":763,"image":902,"draft":767},"Supabase \"invalid input syntax for type uuid\": was im Zitat steht","Supabase \"invalid input syntax for type uuid\" heißt: Deine App hat etwas geschickt, das keine ID ist. Zitat lesen, Abfrage zurückhalten, Spalte behalten.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":904,"title":905,"description":906,"published":907,"category":763,"image":908,"draft":767},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\" erklärt","Supabase \"duplicate key value violates unique constraint\" heißt: Der Wert ist schon vergeben. Spalte finden, Lösung wählen, Wert vom Bildschirm fernhalten.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":414,"title":910,"description":911,"published":912,"category":763,"image":913,"draft":767},"Supabase \"relation does not exist\", obwohl die Tabelle da ist","Supabase \"relation does not exist\" oder PGRST205: Keine Tabelle passt zu Name und Schema deiner Abfrage. Vier Prüfungen, und was eine Freigabe öffnet.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":797,"title":5,"description":766,"published":798,"category":763,"image":785,"draft":767},{"path":204,"title":916,"description":917,"published":918,"category":763,"image":919,"draft":767},"Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" heißt meist: Der Name passt nicht. Vier Prüfungen und der Einzeiler zum Neuladen.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":921,"title":922,"description":923,"published":924,"category":763,"image":925,"draft":767},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": zwei Limits, ein Fehlercode","Supabase \"Email Rate Limit Exceeded\" begrenzt jede E-Mail deines Projekts: 2 pro Stunde beim eingebauten Absender. Was zählt und wie du es anhebst.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":927,"title":928,"description":929,"published":930,"category":763,"image":931,"draft":767},"\u002Fblog\u002Fsupabase-users-logged-out","Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 Ursachen","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" meldet deine Nutzer ab. Drei Ursachen, und wie das Auth-Log sie trennt.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":933,"title":934,"description":935,"published":936,"category":763,"image":937,"draft":767},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": drei Ursachen","Supabase \"permission denied for schema public\" heißt: Ein Grant auf das Schema fehlt. Was ihn entfernt hat und welche Zeile ihn zurückbringt.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":939,"title":940,"description":941,"published":942,"category":763,"image":943,"draft":767},"\u002Fblog\u002Fsupabase-bucket-not-found","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.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":945,"title":946,"description":947,"published":948,"category":763,"image":949,"draft":767},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: Welcher Schlüssel streikt hier?","Ein Supabase invalid JWT ist PGRST301: ein signiertes Token hat die Prüfung nicht bestanden. In neueren Projekten ist das die Sitzung, nicht der API-Schlüssel.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":951,"title":952,"description":953,"published":954,"category":763,"image":955,"draft":767},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" heißt meist: keine Zeilen","Supabase gibt PGRST116 zurück, \"JSON object requested, multiple (or no) rows returned\", wenn die Abfrage nichts fand. Versteckte Zeilen wirken fehlend.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":957,"title":958,"description":959,"published":960,"category":763,"image":961,"draft":767},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" in Supabase: wo du nachsiehst","\"Database error saving new user\" heißt: etwas an deiner Supabase-Registrierung ist fehlgeschlagen. Der echte Fehler steht in deinen Logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":963,"title":964,"description":965,"published":966,"category":763,"image":967,"draft":767},"\u002Fblog\u002Fwhat-is-supabase","Was ist Supabase? Die Datenbank, die dein Builder ausgesucht hat","Was ist Supabase: die Datenbank, der Login und der Dateispeicher hinter deiner App. Supabase betreibt die Server, die Regeln zu deinen Zeilen gehören dir.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":969,"title":970,"description":971,"published":972,"category":763,"image":973,"draft":767},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Ein offengelegter AWS-Schlüssel im Frontend ist kein OpenAI-Key","Ein im Frontend offengelegter AWS-Zugriffsschlüssel liest und schreibt deinen Speicher. Die Lösung ist meist eine presigned URL, kein neuer Schlüssel.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":975,"title":976,"description":977,"published":978,"category":763,"image":979,"draft":767},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" beim Upload","\"New row violates row-level security policy for table objects\" heißt: Deinem Upload fehlt eine insert-Regel. Ein öffentlicher Bucket fügt keine hinzu.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":981,"title":982,"description":983,"published":984,"category":763,"image":985,"draft":767},"\u002Fblog\u002Fbase44-security-scan","Base44 Security Scan: das, was nur er sehen kann","Der Base44 Security Scan prüft sieben Arten von Problemen von innen. Hier ist die Hälfte, die er liest und sonst niemand, und die Hälfte, die er nie ansieht.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":987,"title":988,"description":989,"published":990,"category":763,"image":991,"draft":767},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Dein API-Key wurde geleakt. Die richtige Reihenfolge","Ein API-Key wurde geleakt und du weißt nicht, was zuerst zu tun ist. Nicht jeder Key im Frontend ist ein Leck, und die Reihenfolge zählt mehr als das Tempo.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":419,"title":993,"description":994,"published":995,"category":763,"image":996,"draft":767},"\"Infinite recursion detected in policy\" ohne RLS abzuschalten","\"Infinite recursion detected in policy for relation\" heißt: Deine Policy hat die Tabelle gefragt, die sie schützt. So brichst du den Kreis.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":998,"title":999,"description":1000,"published":1001,"category":763,"image":1002,"draft":767},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" in Supabase, und die falsche Lösung","\"No API key found in request\" heißt, deine Supabase-Anfrage kam ohne Schlüssel an. Die meisten Antworten zeigen stattdessen auf deine Datenbankregeln.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":1004,"title":1005,"description":1006,"published":1007,"category":763,"image":1008,"draft":767},"\u002Fblog\u002Fis-base44-safe","Ist Base44 sicher? Was 5.442 echte Base44-Apps zeigten","Ist Base44 sicher? Wir haben 5.442 laufende Base44-Apps mit neun Checks geprüft. Fast alle bekamen ein B, aus Gründen, die der Inhaber nie gewählt hat.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":1010,"title":1011,"description":1012,"published":1013,"category":763,"image":1014,"draft":767},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","API-Schlüssel verstecken: ab in eine Supabase Edge Function","Einen API-Schlüssel verstecken heißt, ihn aus dem Browser zu nehmen. Eine Supabase Edge Function ist der kleinste Ort dafür, und zwei Schritte zählen mehr.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":1016,"title":1017,"description":1018,"published":1019,"category":763,"image":1020,"draft":767},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Ist deine .env-Datei öffentlich? Zwölf Pfade zum Prüfen","Ist deine .env-Datei auf deinem eigenen Webserver öffentlich? Zwölf Adressen sagen es dir, und ein Treffer heißt: alles darin ist längst öffentlich.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":1022,"title":1023,"description":1024,"published":1025,"category":763,"image":1026,"draft":767},"\u002Fblog\u002Fis-v0-safe","v0-Sicherheit: alle 1.790 gescannten v0-Apps bekamen ein A","v0-Sicherheit, gemessen an 1.790 laufenden v0-Apps: Jede bekam ein A. Nur 17 nannten eine Datenbank, und genau das misst das A vor allem.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":1028,"title":1029,"description":1030,"published":1031,"category":763,"image":1032,"draft":767},"\u002Fblog\u002Fis-bolt-safe","Ist Bolt sicher? Was 1.123 echte Bolt-Apps zeigten","Ist Bolt sicher? Wir haben 1.123 laufende Bolt-Apps mit neun Checks geprüft. Das Hosting war sauber. Die Funde waren Schlüssel und offene Tabellen in den Apps.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":1034,"title":1035,"description":1036,"published":1037,"category":763,"image":1038,"draft":767},"\u002Fblog\u002Fis-supabase-down-or-your-app","Ist Supabase down oder liegt es an deiner App? So erkennst du es","Ist Supabase down oder liegt es an deiner App? Ein pausiertes Projekt, eine volle Datenbank und ein eigener Fehler sehen gleich aus. Vier Prüfungen helfen.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":1040,"title":1041,"description":1042,"published":1043,"category":763,"image":1044,"draft":767},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Verschlüsselt Supabase meine Daten? Ja. Wovor das schützt","Verschlüsselt Supabase Daten? Ja: AES-256 im Ruhezustand, TLS bei der Übertragung, SOC 2 und ISO 27001. Was jedes abdeckt und welches Leck keines stoppt.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":1046,"title":1047,"description":1048,"published":1049,"category":763,"image":1050,"draft":767},"\u002Fblog\u002Fsupabase-free-plan-limits","Supabase Gratis-Tarif: die Limits und was an jedem passiert","Die Limits des Supabase-Gratis-Tarifs: 500 MB Datenbank, 5 GB Egress und keine Backups. Was an jeder Grenze passiert und was $25 für Pro ändern.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":1052,"title":1053,"description":1054,"published":1055,"category":872,"image":1056,"draft":767},"\u002Fblog\u002Ftest-your-supabase-backup","Teste dein Supabase-Backup, bevor du es brauchst","So testest du dein Supabase-Backup: in ein Übungsprojekt einspielen, Zeilen zählen, anmelden und die Zeile suchen, die einer abgeschnittenen Datei fehlt.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":1058,"title":1059,"description":1060,"published":1061,"category":872,"image":1062,"draft":767},"\u002Fblog\u002Fsupabase-backup-github-action","Kostenloses Supabase-Backup per GitHub Action, mit Haken","Eine Supabase-Backup-GitHub-Action kostet nichts und passt für viele Apps. Der Workflow, der richtige Connection String und das Egress pro Lauf.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":1064,"title":1065,"description":1066,"published":1067,"category":872,"image":1068,"draft":767},"\u002Fblog\u002Fdownload-your-supabase-backup","Warum du dein Supabase-Backup nicht herunterladen kannst","Dein Supabase-Backup kannst du auf aktuellen Projekten nicht herunterladen, weil die Tageskopie physisch ist. Wie du es prüfst und selbst eine Kopie hältst.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":1070,"title":1071,"description":1072,"published":1067,"category":763,"image":1073,"draft":767},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": der fehlende Grant","Ab 30. Oktober antwortet eine neue Supabase-Tabelle mit \"permission denied for table\", bis du Zugriff erteilst. Der Grant aus der E-Mail ist die halbe Lösung.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":1075,"title":1076,"description":1077,"published":1078,"category":763,"image":1079,"draft":767},"\u002Fblog\u002Fopen-api-endpoint-exposed","Ist ein offener API-Endpunkt ein Sicherheitsproblem? Sieh ins JSON","Dein Scan hat einen offenen API-Endpunkt gemeldet. Ob das zählt, hängt davon ab, was zurückkam, und die meisten hier gehörten der Plattform.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":1081,"title":1082,"description":1083,"published":1084,"category":763,"image":1085,"draft":767},"\u002Fblog\u002Flovable-security-scan","Lovable Security Scan: das Eine, was er nicht beweist","Lovable Security Scan: was Quick Scan und Deep Scan prüfen, wann welcher läuft, und das Eine, was kein Scan von innen beweisen kann.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":1087,"title":1088,"description":1089,"published":1090,"category":872,"image":1091,"draft":767},"\u002Fblog\u002Fsupabase-backup-auth-users","Warum in deinem Supabase-Dump keine Nutzer stehen","Führe supabase db dump allein aus und du bekommst die Form deiner Datenbank und keine einzige Zeile, und das auth-Schema mit deinen Nutzern fehlt ganz.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":1093,"title":1094,"description":1095,"published":1096,"category":763,"image":1097,"draft":767},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domain abgelaufen, Website offline: was jetzt passiert","Deine Domain ist abgelaufen und deine Website ist offline. Welche Frist jetzt läuft, warum das Zertifikat das kleinere Problem ist, und wie du beides prüfst.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":1099,"title":1100,"description":1101,"published":1102,"category":763,"image":1103,"draft":767},"\u002Fblog\u002Fis-lovable-safe","Ist Lovable sicher? Was 18.554 echte Lovable-Apps zeigten","Ist Lovable sicher? Wir haben 18.554 laufende Lovable-Apps mit neun Checks geprüft. Die Plattform war die sauberste von fünf. Die Funde saßen in den Apps.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":1105,"title":1106,"description":1107,"published":1108,"category":763,"image":1109,"draft":767},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Die Sicherheits-Checkliste für Vibe-Coding, in neun Prüfungen","Eine Sicherheits-Checkliste für Vibe-Coding mit neun Punkten, die jeder von außen an deiner Live-App nachprüfen kann, jeder mit einem Test in einer Zeile.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":1111,"title":1112,"description":1113,"published":1114,"category":763,"image":1115,"draft":767},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Ein geheimer Stripe-Schlüssel im Frontend kann Geld bewegen","Ein geheimer Stripe-Schlüssel im Frontend kann erstatten, abbuchen und jeden Kundendatensatz lesen, den du hast. Dein pk_live_-Schlüssel gehört dorthin.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":1117,"title":1118,"description":1119,"published":1120,"category":763,"image":1121,"draft":767},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen","Vite-Env-Variablen offengelegt: Deine App hat getan, was der Präfix verlangt. VITE_ und NEXT_PUBLIC_ heißen veröffentlichen, und die KI kannte den Preis nie.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":1123,"title":1124,"description":1125,"published":1126,"category":763,"image":1127,"draft":767},"\u002Fblog\u002Fbase44-source-maps","Base44-Sicherheit: was ein Scan meldet und was du ändern kannst","Base44-Sicherheit auf 5.438 gescannten Apps: Drei Befunde auf fast jeder gehören der Plattform, die Source Map ist das Base44-Badge, und deine Liste ist kurz.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":1129,"title":1130,"description":1131,"published":1132,"category":763,"image":1133,"draft":767},"\u002Fblog\u002Fis-cursor-ai-safe","Ist Cursor AI sicher? Editor, Code und die App, die du veröffentlichst","Ist Cursor AI sicher? Drei Fragen in einer Suche: was Cursor behält, was sein Code falsch macht und ob deine veröffentlichte App offen steht.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":1135,"title":1136,"description":1137,"published":1138,"category":763,"image":1139,"draft":767},"\u002Fblog\u002Fis-replit-safe","Ist Replit sicher? Was wir in 3.042 Replit-Apps gefunden haben","Ist Replit sicher? Wir haben 3.042 laufende Replit-Apps mit neun externen Checks geprüft. Die Funde saßen in der veröffentlichten App, nicht im Hosting.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":1141,"title":1142,"description":1143,"published":1144,"category":872,"image":1145,"draft":767},"\u002Fblog\u002Fsupabase-storage-backup","Supabase Storage Backup: deine Datenbankkopie hat keine Dateien","Ein Supabase Storage Backup ist eine eigene Aufgabe. Datenbank-Backups enthalten die Liste deiner Dateien und keine davon, also bleibt jeder Upload kaputt.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":1147,"title":1148,"description":1149,"published":1150,"category":872,"image":1151,"draft":767},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Supabase Point-in-Time Recovery: Kosten und Grenzen","Supabase Point-in-Time Recovery spult deine Datenbank auf jede Sekunde der letzten Woche zurück. $100 im Monat zusätzlich zu Pro, und nur die Datenbank.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":1153,"title":1154,"description":1155,"published":1156,"category":872,"image":1157,"draft":767},"\u002Fblog\u002Fsupabase-project-paused-recover","Supabase-Projekt pausiert? Deine Daten sind noch da","Supabase hat dein Projekt nach einer Woche ohne Aktivität pausiert. Gelöscht ist nichts, Wiederherstellen steht neben dem Namen, und du hast ein Jahr.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":1159,"title":1160,"description":1161,"published":1162,"category":763,"image":1163,"draft":767},"\u002Fblog\u002Fsafest-ai-app-builder","Welcher KI-App-Builder ist am sichersten? 30.998 Apps im Test","Welcher KI-App-Builder ist am sichersten? Wir haben 30.998 aktive Apps von Lovable, Base44, Replit, v0 und Bolt gescannt. Der Builder entscheidet das nicht.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":409,"title":1165,"description":1166,"published":1167,"category":763,"image":1168,"draft":767},"Row Level Security für jede Supabase-Tabelle aktivieren und prüfen","Row Level Security in Supabase ohne Policy sperrt eine Tabelle komplett. Eine Policy ohne den Schalter bringt gar nichts. Hier ist das SQL, und der Test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":1170,"title":1171,"description":1172,"published":1173,"category":763,"image":1174,"draft":767},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": was die Warnung übersieht","Supabase meldet \"RLS disabled in public\" als Fehler. Zur Lese-Policy, die deine Tabelle genauso offen lässt, sagt der Advisor gar nichts.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":1176,"title":1177,"description":1178,"published":1179,"category":763,"image":1180,"draft":767},"\u002Fblog\u002Frotate-supabase-service-role-key","Geleakten Supabase-service_role-Schlüssel richtig tauschen","Supabase sagt: erst das Leck schließen. Andere Anleitungen: sofort tauschen. Was richtig ist, hängt davon ab, wohin dein service_role-Schlüssel gelangt ist.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1182,"title":1183,"description":1184,"published":1185,"category":763,"image":1186,"draft":767},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Vibe-Coding-Security-Scanner im Vergleich, unserer eingeschlossen","Der beste Vibe-Coding-Security-Scanner hängt an drei Fragen, die keine Funktionsliste beantwortet. Acht Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1188,"title":1189,"description":1190,"published":1191,"category":763,"image":1192,"draft":767},"\u002Fblog\u002Fsupabase-security-checker","Supabase Security Checker: die fünf Prüfungen selbst machen","Ein Supabase Security Checker liest deine veröffentlichte App statt deiner Projekteinstellungen. Hier sind die fünf Prüfungen und wie du jede selbst ausführst.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1194,"title":1195,"description":1196,"published":1197,"category":763,"image":1198,"draft":767},"\u002Fblog\u002Fvibe-coding-security-scanner","Vibe-Coding-Security-Scanner: was ein URL-Scan übersieht","Ein Vibe-Coding-Security-Scanner liest deine laufende App von außen. Was das abdeckt, die vier Dinge, die er nicht sehen kann, und wie du das Ergebnis liest.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1200,"title":1201,"description":1202,"published":1203,"category":763,"image":1204,"draft":767},"\u002Fblog\u002Fmissing-security-headers","Fehlende Sicherheitsheader: wann sie wirklich zählen","Fehlende Sicherheitsheader ist unser häufigster Befund. Wogegen sie schützen, und wann sie die unwichtigste Zeile in deinem Bericht sind.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1206,"title":1207,"description":1208,"published":1209,"category":763,"image":1210,"draft":767},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Dein OpenAI-API-Schlüssel liegt im Frontend. Tausch ihn aus.","Ein OpenAI-API-Schlüssel im Frontend lässt sich an keine Domain binden. Tausch ihn heute, leg den Aufruf hinter deinen Server und begrenze das Budget.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1212,"title":1213,"description":1214,"published":1215,"category":763,"image":1216,"draft":767},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","API-Schlüssel im Frontend: was 30.998 Apps wirklich ausliefern","Ein API-Schlüssel im Frontend ist meistens ein Google-Maps-Schlüssel. Wir haben 30.998 aktive Vibe-Coding-Apps gescannt und gezählt, was wirklich austritt.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1218,"title":1219,"description":1220,"published":1221,"category":872,"image":1222,"draft":767},"\u002Fblog\u002Fsupabase-backup-tools-compared","Supabase-Backup-Tools im Vergleich, unseres eingeschlossen","Vier Arten von Supabase-Backup-Tool, was jedes wirklich kopiert und wann eine kostenlose GitHub Action jeden Anbieter schlägt, uns eingeschlossen.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1224,"title":1225,"description":1226,"published":1227,"category":763,"image":1228,"draft":767},"\u002Fblog\u002Freplit-secrets-explained","Secrets in Replit nutzen, und was trotzdem veröffentlicht wird","Secrets in Replit nutzen: anlegen, auslesen und die zwei Gründe beheben, warum undefined zurückkommt. Dazu die Schlüssel, die das Werkzeug nicht schützt.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1230,"title":1231,"description":1232,"published":1233,"category":872,"image":1234,"draft":767},"\u002Fblog\u002Fback-up-supabase-free-tier","Supabase Gratis-Tarif: Backup ohne Terminal selbst machen","Im Supabase Gratis-Tarif gibt es keine Backups, die Kopie musst du selbst machen. Wie das im Dashboard geht und was der CSV-Weg auslässt.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1236,"title":1237,"description":1238,"published":1239,"category":763,"image":1240,"draft":767},"\u002Fblog\u002Fis-supabase-secure","Ist Supabase sicher? Ja. Dein Projekt ist eine eigene Frage","Ist Supabase sicher? Die Plattform ist auditiert, verschlüsselt und pentestet. Supabase schreibt selbst auf, wo das aufhört und deine Einstellungen anfangen.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1242,"title":1243,"description":1244,"published":1245,"category":763,"image":1246,"draft":767},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Wo du deine Supabase API-Keys findest: anon, service_role, URL","Projekt-URL, anon-Schlüssel und service_role-Schlüssel liegen auf einer Seite im Dashboard. Wo sie ist, und welcher der vier Werte in deine App gehört.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1248,"title":1249,"description":1250,"published":1251,"category":763,"image":1252,"draft":767},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy in Supabase: was jetzt?","\"New row violates row-level security policy\" heißt, Supabase hat einen Schreibvorgang abgelehnt. Die schnelle Lösung öffnet die Tabelle wieder für alle.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1254,"title":1255,"description":1256,"published":1257,"category":763,"image":1258,"draft":767},"\u002Fblog\u002Fcors-wildcard-security-risk","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist nicht.","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist ist sie die Voreinstellung deines Builders und gibt nichts preis, was dein Server nicht ohnehin herausgab.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":479,"title":1260,"description":1261,"published":1262,"category":872,"image":1263,"draft":767},"Supabase Branching ist kein Backup. Es geht nur vorwärts.","Warum Supabase Branching kein Backup ist: Ein Branch startet ohne deine Daten, und ein Merge bringt nur das Schema. Wofür es gut ist und was stattdessen hilft.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":1265,"title":1266,"description":1267,"published":1268,"category":872,"image":1269,"draft":767},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Supabase-Backup wiederherstellen, und was danach kaputt ist","Wie du ein Supabase-Backup aus dem Dashboard oder aus einer Dump-Datei wiederherstellst, was ersetzt wird und warum die App danach kaputt sein kann.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1271,"title":1272,"description":1273,"published":1274,"category":763,"image":1275,"draft":767},"\u002Fblog\u002Fsupabase-storage-bucket-public","Dein Supabase-Storage-Bucket ist öffentlich. Ist das ein Problem?","Ein öffentlicher Supabase-Storage-Bucket heißt: Wer die URL einer Datei hat, kann sie öffnen. Er heißt nicht, dass jemand den Inhalt auflisten darf.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1277,"title":1278,"description":1279,"published":1280,"category":763,"image":1281,"draft":767},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Ist ein Google-API-Schlüssel im Frontend ein Problem?","Ein Google-API-Schlüssel im Frontend ist der Fund unseres Scanners Nummer eins, und meistens unbedenklich. Eine kostenlose Einstellung entscheidet darüber.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1283,"title":1284,"description":1285,"published":1286,"category":872,"image":1287,"draft":767},"\u002Fblog\u002Fai-agent-deleted-my-database","Ein KI-Agent hat meine Supabase-Daten gelöscht. Was hole ich zurück?","Ein KI-Agent hat Daten aus deiner Datenbank gelöscht. Was du zurückholst, stand schon vorher fest, und die nächsten Minuten entscheiden über den Rest.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1289,"title":1290,"description":1291,"published":1292,"category":763,"image":1293,"draft":767},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Kann jeder deine Supabase-Datenbank lesen? 3.680 Apps im Test","Kann jeder deine Supabase-Datenbank ohne Login lesen? Wir haben 30.998 aktive Apps aus KI-Buildern gescannt und gemessen, wie oft die Antwort ja lautet.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1295,"title":1296,"description":1297,"published":1292,"category":763,"image":1298,"draft":767},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source-Maps öffentlich: deine App veröffentlicht ihren Quellcode","Eine öffentliche Source-Map lässt jeden den Originalcode deiner App lesen, Kommentare inklusive. Der 30-Sekunden-Check, und was wirklich zählt.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1300,"title":1301,"description":1302,"published":1303,"category":763,"image":1304,"draft":767},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: ist er derselbe wie der anon key?","Supabase hat anon und service_role durch öffentliche und geheime Schlüssel ersetzt. Welcher gehört in deine App, und welcher nie?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1306,"title":1307,"description":1308,"published":1309,"category":872,"image":1310,"draft":767},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Sichert Supabase meine Datenbank? Das hängt von deinem Tarif ab.","Sichert Supabase deine Datenbank? Auf bezahlten Tarifen täglich, im Gratis-Tarif gar nicht. So findest du heraus, was du hast und was es nicht abdeckt.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1312,"title":1313,"description":1314,"published":1315,"category":763,"image":1316,"draft":767},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security ist an. Die Tabelle ist trotzdem offen.","Supabase Row Level Security anzuschalten schützt keine Tabelle. Erst deine Policies tun das, und die, die deine App repariert hat, lässt oft alle herein.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1318,"title":1319,"description":1320,"published":1315,"category":872,"image":1321,"draft":767},"\u002Fblog\u002Fversion-history-is-not-a-backup","Der Versionsverlauf ist kein Backup. Er holt keine Tabelle zurück.","Lovable und Bolt führen einen Versionsverlauf für deinen Code. Deine Datenbank ist ein eigener Dienst, und ein Rücksprung holt deine Daten nicht zurück.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1323,"title":1324,"description":1325,"published":1326,"category":872,"image":1327,"draft":767},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Drei Wege, eine Supabase-Datenbank zu sichern, und was fehlt","Das Dashboard, pg_dump und ein verwalteter Dienst. Was jeder Weg wirklich sichert, was er stillschweigend auslässt und welcher den Kontoverlust übersteht.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1329,"title":1330,"description":1331,"published":1326,"category":763,"image":1332,"draft":767},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Welche API-Schlüssel im Frontend sicher sind, und welche nicht","Dein Supabase-anon-Schlüssel darf öffentlich sein. Der service_role-Schlüssel nicht. Er ignoriert jede Regel, die du setzt. So erkennst du den Unterschied.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1794213638733]