[{"data":1,"prerenderedAt":1388},["ShallowReactive",2],{"blog-de-supabase-relation-does-not-exist":3,"blog-index-de":862},{"id":4,"title":5,"body":6,"category":818,"cover":819,"coverAlt":820,"description":821,"draft":822,"extension":823,"faq":824,"image":840,"keywords":841,"meta":851,"navigation":852,"ogTitle":5,"path":853,"published":854,"seo":855,"stem":856,"tldr":857,"updated":854,"__hash__":861},"blog_de\u002Fblog\u002Fsupabase-relation-does-not-exist.md","Supabase \"relation does not exist\", obwohl die Tabelle da ist",{"type":7,"value":8,"toc":805},"minimark",[9,18,28,35,38,43,62,73,76,149,182,193,197,200,209,245,302,314,317,325,336,340,353,356,405,421,427,440,445,451,455,458,466,472,486,493,496,502,519,522,528,536,541,545,551,554,560,567,582,586,598,610,613,619,626,644,649,653,656,667,676,680,683,693,716,725,743,747,798],[10,11,12,13,17],"p",{},"Dein Builder hat eine Tabelle ",[14,15,16],"code",{},"invoices"," angelegt. Du siehst sie im Table Editor,\nsamt Zeilen, und die Seite, die sie auflisten soll, bleibt leer. Die\nBrowserkonsole zeigt das hier:",[19,20,25],"pre",{"className":21,"code":23,"language":24},[22],"language-text","{\n  \"code\": \"PGRST205\",\n  \"details\": null,\n  \"hint\": \"Perhaps you meant the table 'public.Invoices'\",\n  \"message\": \"Could not find the table 'public.invoices' in the schema cache\"\n}\n","text",[14,26,23],{"__ignoreMap":27},"",[10,29,30,31,34],{},"Supabase \"relation does not exist\" heißt, dass Postgres in den Schemas, die die\nAbfrage durchsucht hat, keine Tabelle und keinen View mit genau diesem Namen\ngefunden hat. PGRST205 ist dieselbe Antwort von PostgREST, dem Teil von Supabase,\nder die Aufrufe ",[14,32,33],{},"supabase.from(...)"," deiner App in Datenbankabfragen übersetzt,\ngegeben, bevor die Abfrage Postgres überhaupt erreicht.",[10,36,37],{},"Die Lösung, die für diesen Fehler herumgereicht wird, lautet: das Schema in den\nProjekteinstellungen unter Exposed schemas eintragen. Das behebt eine der vier\nUrsachen unten. Es macht außerdem jede Tabelle in diesem Schema für jeden\nerreichbar, der den öffentlichen Schlüssel deiner App hat. Lies also, was es\nöffnet, bevor du es einschaltest.",[39,40,42],"h2",{"id":41},"was-bedeutet-relation-does-not-exist-in-supabase","Was bedeutet \"relation does not exist\" in Supabase?",[10,44,45,46,49,50,61],{},"Die Datenbank hat eine Tabelle mit genau diesem Namen gesucht, in den Schemas, die\nsie durchsuchen sollte, und keine gefunden. \"Relation\" ist das Wort von Postgres\nfür alles, woraus Zeilen kommen, also eine Tabelle oder einen View. Der Code des\nFehlers ist ",[14,47,48],{},"42P01",", den\n",[51,52,56,57,60],"a",{"href":53,"rel":54},"https:\u002F\u002Fgithub.com\u002Fpostgres\u002Fpostgres\u002Fblob\u002Fmaster\u002Fsrc\u002Fbackend\u002Futils\u002Ferrcodes.txt",[55],"nofollow","Postgres ",[14,58,59],{},"undefined_table"," nennt",".",[10,63,64,65,68,69,72],{},"Stell dir deine Datenbank als Gebäude vor. Jedes Schema ist eine Etage: ",[14,66,67],{},"public","\nist das Erdgeschoss, und ",[14,70,71],{},"auth",", wo Supabase deine Nutzer aufbewahrt, ist eine\nandere. Jede Tabelle ist ein Raum mit ihrem Namen an der Tür. Eine Abfrage, die\nnur den Namen eines Raums nennt, wird auf den Etagen gesucht, die in ihrem Suchpfad\nstehen. Die Anfragen deiner App fahren mit einem Aufzug, und der Aufzug hält nur\nauf den Etagen, die dein Projekt freigibt. Der Fehler heißt: Auf den Etagen, die\ngeprüft wurden, hat niemand eine Tür mit diesem Namen gefunden.",[10,74,75],{},"Welchen Wortlaut du siehst, hängt davon ab, wo die Abfrage lief:",[77,78,79,92],"table",{},[80,81,82],"thead",{},[83,84,85,89],"tr",{},[86,87,88],"th",{},"Wo die Abfrage lief",[86,90,91],{},"Was zurückkommt",[93,94,95,109,123,135],"tbody",{},[83,96,97,101],{},[98,99,100],"td",{},"Im SQL Editor, in einer Migration, einer Funktion oder einem Trigger",[98,102,103,106,107],{},[14,104,105],{},"relation \"invoices\" does not exist",", Code ",[14,108,48],{},[83,110,111,114],{},[98,112,113],{},"In deiner App, mit PostgREST 13 oder neuer",[98,115,116,106,119,122],{},[14,117,118],{},"Could not find the table 'public.invoices' in the schema cache",[14,120,121],{},"PGRST205",", HTTP 404",[83,124,125,128],{},[98,126,127],{},"In deiner App, mit einem älteren PostgREST",[98,129,130,131,134],{},"ein Lesezugriff bekommt ",[14,132,133],{},"relation \"public.invoices\" does not exist",", HTTP 404, und ein Insert einen leeren Fehler",[83,136,137,140],{},[98,138,139],{},"In deiner App, die ein Schema anfragt, das das Projekt nicht freigibt",[98,141,142,106,145,148],{},[14,143,144],{},"Invalid schema: billing",[14,146,147],{},"PGRST106",", HTTP 406",[10,150,151,152,157,158,160,161,166,167,169,170,175,176,181],{},"Das ",[51,153,156],{"href":154,"rel":155},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002FCHANGELOG.md",[55],"Changelog von PostgREST","\ndatiert den neueren Wortlaut auf Version 13.0.0, erschienen am 8. Mai 2025:\n\"Querying non-existent table now returns ",[14,159,121],{}," error\". Davor ging ein\nLesezugriff, wie einer der Maintainer\n",[51,162,165],{"href":163,"rel":164},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fissues\u002F3697",[55],"in Issue #3697 erklärt",",\nungeprüft an Postgres und kam als ",[14,168,48],{}," zurück. Supabases\n",[51,171,174],{"href":172,"rel":173},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fdatabase\u002Fhardening-data-api",[55],"Anleitung zur Absicherung der Data API","\nsagt, dass du die PostgREST-Version deines Projekts im Dashboard prüfen kannst.\n",[51,177,180],{"href":178,"rel":179},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FError.hs",[55],"Der eigene Code von PostgREST","\nlegt den Rest fest: Der Hinweis von PGRST205 nennt, wenn es einen gibt, die\nähnlichste Tabelle, die es auf derselben Etage kennt.",[10,183,184,185,188,189,61],{},"Steht in der Meldung stattdessen ",[14,186,187],{},"permission denied for table",", wurde die Tabelle\ngefunden, und deine App wurde an der Tür abgewiesen. Dafür gibt es\n",[51,190,192],{"href":191},"\u002Fblog\u002Fsupabase-permission-denied-for-table","eine andere Lösung",[39,194,196],{"id":195},"ursache-1-der-name-an-der-tür-hat-einen-großbuchstaben","Ursache 1: Der Name an der Tür hat einen Großbuchstaben",[10,198,199],{},"Der Name muss genau passen, samt Großbuchstaben, und zwei der Werkzeuge, die du\nbenutzt, behandeln Großbuchstaben anders als das dritte.",[10,201,202,203,208],{},"Die\n",[51,204,207],{"href":205,"rel":206},"https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002Fcurrent\u002Fsql-syntax-lexical.html",[55],"Dokumentation von Postgres","\nfasst die Regel in einem Satz: \"Quoting an identifier also makes it\ncase-sensitive, whereas unquoted names are always folded to lower case.\" Die\nbeiden anderen behalten, was du getippt hast:",[210,211,212,227],"ul",{},[213,214,215,216,221,222,225,61],"li",{},"Der Table Editor von Supabase legt eine Tabelle unter genau dem Namen an, den du\nihr gibst.\n",[51,217,220],{"href":218,"rel":219},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fsupabase\u002Fblob\u002Fmaster\u002Fpackages\u002Fpg-meta\u002Fsrc\u002Fpg-meta-tables.ts",[55],"Sein Code","\nsetzt den Namen in Anführungszeichen, wenn er sie braucht, also bleibt ",[14,223,224],{},"Invoices",[14,226,224],{},[213,228,229,230,237,238,241,242,244],{},"PostgREST setzt jeden Namen, den deine App schickt, in doppelte Anführungszeichen\n(",[51,231,234],{"href":232,"rel":233},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FQuery\u002FSqlFragment.hs",[55],[14,235,236],{},"pgFmtIdent","),\nalso fragt ",[14,239,240],{},".from('invoices')"," nach ",[14,243,16],{}," und nach nichts anderem.",[77,246,247,260],{},[80,248,249],{},[83,250,251,254,257],{},[86,252,253],{},"Wie die Tabelle angelegt wurde",[86,255,256],{},"In SQL schreibst du",[86,258,259],{},"In deiner App schreibst du",[93,261,262,281],{},[83,263,264,273,277],{},[98,265,266,269,270,272],{},[14,267,268],{},"create table invoices",", oder ",[14,271,224],{}," in SQL ohne Anführungszeichen",[98,274,275],{},[14,276,16],{},[98,278,279],{},[14,280,240],{},[83,282,283,291,297],{},[98,284,285,269,288,290],{},[14,286,287],{},"create table \"Invoices\"",[14,289,224],{}," im Table Editor eingetippt",[98,292,293,296],{},[14,294,295],{},"\"Invoices\"",", mit Anführungszeichen",[98,298,299],{},[14,300,301],{},".from('Invoices')",[10,303,304,305,307,308,310,311,313],{},"Die zweite Zeile erzeugt diesen Fehler von beiden Seiten. Deine App ruft\n",[14,306,240],{}," auf und bekommt PGRST205, mit dem echten Namen im Hinweis, wie\nin der Meldung oben auf dieser Seite. Oder die App funktioniert, und eine Funktion\noder eine Policy, die ",[14,309,224],{}," ohne Anführungszeichen nennt, scheitert mit\n",[14,312,105],{},", weil Postgres den Namen umgewandelt hat,\nbevor es suchte.",[10,315,316],{},"Um jede Tabelle mit diesem Namen zu sehen, auf jeder Etage und in jeder\nSchreibweise, führ das im SQL Editor aus:",[19,318,323],{"className":319,"code":321,"language":322,"meta":27},[320],"language-sql","select table_schema, table_name\nfrom information_schema.tables\nwhere table_name ilike 'invoices';\n","sql",[14,324,321],{"__ignoreMap":27},[10,326,327,328,330,331,335],{},"Die Lösung, die an deinen Daten nichts ändert, liegt im Code: Schreib in SQL\n",[14,329,295],{}," mit seinen Anführungszeichen und in der App genau die\nGroßbuchstaben. Die Tabelle stattdessen umzubenennen bricht jede Seite, die noch\nden alten Namen benutzt.\n",[51,332,334],{"href":333},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Die Spaltenversion dieses Fehlers"," hat\ndieselbe Falle bei Spaltennamen.",[39,337,339],{"id":338},"ursache-2-die-tabelle-liegt-auf-einer-anderen-etage","Ursache 2: Die Tabelle liegt auf einer anderen Etage",[10,341,342,343,345,346,349,350,352],{},"Deine App sucht in ",[14,344,67],{},", solange man ihr nichts anderes sagt, also fehlt eine\nTabelle in jedem anderen Schema, soweit sie das sehen kann. Deshalb sagt die\nMeldung ",[14,347,348],{},"public.invoices",": ",[14,351,67],{}," ist die Etage, zu der der Aufzug gefahren ist.",[10,354,355],{},"Das passiert auf drei Arten:",[210,357,358,372,381],{},[213,359,360,361,364,365,368,369,371],{},"dein Builder hat die Tabelle in einem eigenen Schema angelegt, etwa ",[14,362,363],{},"billing","\noder ",[14,366,367],{},"private",", und die App ruft ein schlichtes ",[14,370,240],{}," auf",[213,373,374,375,378,379],{},"das Schema steht im Namen, als ",[14,376,377],{},".from('billing.invoices')",". PostgREST liest die\nganze Zeichenkette als einen Tabellennamen und sucht ihn in ",[14,380,67],{},[213,382,383,384,387,388,393,394,396,397,400,401],{},"die Tabelle ist ",[14,385,386],{},"auth.users",". Supabases\n",[51,389,392],{"href":390,"rel":391},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fmanaging-user-data",[55],"Anleitung zu Nutzerdaten","\nsagt: \"For security, the Auth schema is not exposed in the auto-generated API.\"\nIhre Antwort ist eine eigene Tabelle in ",[14,395,67],{},", in ihrem Beispiel ",[14,398,399],{},"profiles",",\ngefüllt von einem Trigger, wenn sich jemand registriert, und\n",[51,402,404],{"href":403},"\u002Fblog\u002Fdatabase-error-saving-new-user","dieser Trigger kann auf eigene Arten scheitern",[10,406,407,408,411,412,417,418,420],{},"Eine Tabelle auf einer anderen Etage liest du mit\n",[14,409,410],{},".schema('billing').from('invoices')",", und dieses Schema muss in den\nAPI-Einstellungen des Projekts unter Exposed schemas stehen, wie\n",[51,413,416],{"href":414,"rel":415},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fapi\u002Fusing-custom-schemas",[55],"Supabases Anleitung zu eigenen Schemas","\nzeigt. Bis dahin ändert sich die Antwort zu ",[14,419,147],{},":",[19,422,425],{"className":423,"code":424,"language":24},[22],"{\n  \"code\": \"PGRST106\",\n  \"details\": null,\n  \"hint\": \"Only the following schemas are exposed: public, graphql_public\",\n  \"message\": \"Invalid schema: billing\"\n}\n",[14,426,424],{"__ignoreMap":27},[10,428,429,430,433,434,439],{},"Der Hinweis zählt die Etagen auf, an denen der Aufzug hält. PostgREST 12 formuliert\ndenselben Fehler anders, mit der Liste in der Meldung selbst:\n",[14,431,432],{},"The schema must be one of the following: public, graphql_public",". Das ist der\nText, den ",[51,435,438],{"href":436,"rel":437},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fv12.2.12\u002Fsrc\u002FPostgREST\u002FError.hs",[55],"sein Code für diese Version","\nerzeugt, und laut Changelog kam der Schemaname in 13.0.7 in die Meldung.",[10,441,442,443,61],{},"Dein geheimer Schlüssel fährt im selben Aufzug. Die Freigabe ist eine Einstellung\nder API, also bekommt Servercode, der supabase-js mit diesem Schlüssel benutzt,\ndasselbe ",[14,444,147],{},[446,447],"diagram",{"alt":448,"caption":449,"src":450},"Ein Gebäude im Querschnitt mit drei Etagen, unten public, in der Mitte billing und oben auth, und rechts ein Aufzugsschacht. Der Aufzug hält bei public, wo die Tür invoices ein gestrichelter leerer Platz ist, der zu einer Plakette mit PGRST205 und 404 führt. Sein Halt bei billing, wo die Tür invoices steht, ist eine gestrichelte bernsteinfarbene Lücke, die zu einer Plakette mit PGRST106 und 406 führt. Die Etage auth hat gar keinen Halt.","Der Aufzug hält nur auf freigegebenen Etagen. Eine Tabelle auf einer anderen Etage fehlt in public, und wer diese Etage beim Namen verlangt, wird abgewiesen, bis sie freigegeben ist.","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fthe-lift-stops-at-public-1600x760.png",[39,452,454],{"id":453},"was-öffnet-ein-freigegebenes-schema","Was öffnet ein freigegebenes Schema?",[10,456,457],{},"Der Aufzug hält dann auf dieser Etage, und mit den Berechtigungen aus Supabases\nAnleitung bekommt jeder Besucher einen Schlüssel zu jedem Raum dort. Row Level\nSecurity entscheidet dann als Einziges, was jeder von ihnen lesen oder ändern kann.",[10,459,460,461,465],{},"Die ",[51,462,464],{"href":414,"rel":463},[55],"Anleitung zu eigenen Schemas","\nhat zwei Schritte. Der erste ist die Einstellung Exposed schemas. Der zweite ist\nein SQL-Block, und seine ersten beiden Zeilen lauten:",[19,467,470],{"className":468,"code":469,"language":322,"meta":27},[320],"GRANT USAGE ON SCHEMA myschema TO anon, authenticated, service_role;\nGRANT ALL ON ALL TABLES IN SCHEMA myschema TO anon, authenticated, service_role;\n",[14,471,469],{"__ignoreMap":27},[10,473,474,477,478,481,482,485],{},[14,475,476],{},"anon"," ist die Rolle hinter jeder Anfrage von jemandem, der nicht angemeldet ist.\n",[14,479,480],{},"ALL"," heißt lesen, hinzufügen, ändern und löschen. Der Block geht weiter mit\n",[14,483,484],{},"ALTER DEFAULT PRIVILEGES",", das denselben Zugriff jeder Tabelle gibt, die später\nauf dieser Etage angelegt wird.",[10,487,488,489,492],{},"Sicher ist das dort, wo Row Level Security, die Regeln pro Zeile, die Supabase bei\njeder Anfrage prüft, eingeschaltet und für jede Tabelle geschrieben ist. Supabases\n",[51,490,174],{"href":172,"rel":491},[55],"\nsagt: \"Tables created through the Supabase Dashboard have RLS enabled by default.\nEnable RLS explicitly for tables created in the SQL Editor or through another\ntool.\" Ein Schema, das dein Builder in SQL eingerichtet hat, kann Tabellen ohne sie\nenthalten. Mit diesen Berechtigungen freigegeben, gibt so eine Tabelle jede Zeile an\njeden heraus, der deinen öffentlichen Schlüssel hat, und nimmt auch seine\nÄnderungen an.",[10,494,495],{},"Prüf vor der Freigabe:",[19,497,500],{"className":498,"code":499,"language":322,"meta":27},[320],"select tablename, rowsecurity\nfrom pg_tables\nwhere schemaname = 'billing';\n",[14,501,499],{"__ignoreMap":27},[10,503,504,505,508,509,513,514,518],{},"Jede Zeile mit ",[14,506,507],{},"false"," ist eine Tabelle ganz ohne Regeln.\n",[51,510,512],{"href":511},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security für jede Tabelle einschalten","\nbehandelt das Einschalten und die erste Regel, und\n",[51,515,517],{"href":516},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","\"RLS disabled in public\""," behandelt die\noffene Leseregel, die eine Tabelle auch mit eingeschalteter Row Level Security\ngenauso erreichbar lässt.",[10,520,521],{},"Du kannst auch weniger freigeben als die Anleitung. Eine Etage mit einer Tabelle,\ndie nur angemeldete Nutzer lesen, braucht zwei Zeilen:",[19,523,526],{"className":524,"code":525,"language":322,"meta":27},[320],"grant usage on schema billing to authenticated;\ngrant select on billing.invoices to authenticated;\n",[14,527,525],{"__ignoreMap":27},[10,529,530,531,535],{},"Ob deine Tabellen einem Fremden antworten, kannst du von außen prüfen. Unser\n",[51,532,534],{"href":533},"\u002Fsecurity-scanner","kostenloser Scan"," liest deine laufende App mit demselben\nöffentlichen Schlüssel, den ein Besucher bekommt, meldet, welche Tabellen Zeilen\nherausgeben, und braucht kein Konto.",[446,537],{"alt":538,"caption":539,"src":540},"Die Etage billing zweimal gezeichnet. Links hat der Aufzug dort keinen Halt, und drei Türen sind zu. Rechts hält der Aufzug dort, und alle drei Türen stehen offen: Zwei Räume haben ein Vorhängeschloss über ihren Zeilen, der dritte hat keines, und seine Zeilen sind bernsteinfarben.","Eine Etage mit den Berechtigungen der Anleitung freizugeben öffnet jede Tür darauf. Row Level Security ist das Vorhängeschloss in jedem Raum, und ein Raum ohne eines steht jedem offen, der deinen öffentlichen Schlüssel hat.","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fexposing-opens-every-room-1600x700.png",[39,542,544],{"id":543},"schema-freigeben-oder-tabelle-verschieben","Schema freigeben oder Tabelle verschieben?",[10,546,547,548,550],{},"Entscheide danach, wer die Tabelle liest. Eine Tabelle, die deine App aus dem\nBrowser liest, braucht eine Berechtigung für die Rolle, die liest, und Row Level\nSecurity mit einer Regel, egal wo sie liegt. Sie nach ",[14,549,67],{}," zu verschieben spart\ndir also den Schritt der Freigabe und sonst nichts.",[10,552,553],{},"Wenn du sie verschiebst:",[19,555,558],{"className":556,"code":557,"language":322,"meta":27},[320],"alter table billing.invoices set schema public;\n",[14,559,557],{"__ignoreMap":27},[10,561,562,563,566],{},"Die Tabelle behält ihre Berechtigungen und ihre Regeln. Eine Funktion, deren Körper\n",[14,564,565],{},"billing.invoices"," nennt, scheitert danach mit genau diesem Fehler, weil der Körper\nden Namen so behält, wie er geschrieben wurde.",[10,568,569,570,572,573,577,578,581],{},"Eine Tabelle, die nur Servercode braucht, kann auf einer Etage bleiben, die der\nAufzug nie anfährt. Eine Funktion in ",[14,571,67],{}," kann die eine Aufgabe damit\nerledigen, die deine App braucht, und\n",[51,574,576],{"href":575},"\u002Fblog\u002Fsupabase-function-not-found","eine Supabase-Funktion aufrufen"," zeigt, wie du\nBesuchern, die nicht angemeldet sind, das Recht ",[14,579,580],{},"execute"," wegnimmst.",[39,583,585],{"id":584},"ursache-3-eine-funktion-mit-leerem-suchpfad","Ursache 3: Eine Funktion mit leerem Suchpfad",[10,587,588,589,592,593,595,596,61],{},"Eine Funktion mit ",[14,590,591],{},"search_path = ''"," durchsucht gar keine Etage, also braucht jede\nTabelle darin ihr Schema davor: ",[14,594,348],{},", nie ein nacktes ",[14,597,16],{},[10,599,600,601,609],{},"Der Security Advisor von Supabase verlangt genau diese Einstellung. Seine\n",[51,602,605,606],{"href":603,"rel":604},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fsplinter\u002Fblob\u002Fmain\u002Fdocs\u002F0011_function_search_path_mutable.md",[55],"Warnung ",[14,607,608],{},"function_search_path_mutable","\nsagt: \"We recommend pinning functions' search_path to an empty string\". Dieselbe\nSeite endet mit: \"once you set the search_path = '' all references to\ntables\u002Ffunctions\u002Fviews\u002Fetc in your function's body must be qualified with a\nschema name.\"",[10,611,612],{},"Die Warnung wird also mit einer Zeile behoben, und die Funktion scheitert danach am\nersten nackten Tabellennamen:",[19,614,617],{"className":615,"code":616,"language":322,"meta":27},[320],"create or replace function public.count_invoices()\nreturns bigint\nlanguage plpgsql\nset search_path = ''\nas $$\nbegin\n  return (select count(*) from invoices);  -- relation \"invoices\" does not exist\nend;\n$$;\n",[14,618,616],{"__ignoreMap":27},[10,620,621,622,625],{},"Schreib ",[14,623,624],{},"from public.invoices",", und sie funktioniert wieder. Behalte die\nEinstellung: Sie sorgt dafür, dass niemand, der die Funktion aufruft, einen nackten\nNamen auf eine eigene Tabelle umlenken kann.",[10,627,628,629,632,633,635,636,640,641,61],{},"Aus deiner App mit ",[14,630,631],{},".rpc()"," aufgerufen, geht der Fehler als ",[14,634,48],{}," mit HTTP 404\ndurch PostgREST, dem Status, den\n",[51,637,639],{"href":178,"rel":638},[55],"der Code von PostgREST","\neiner unbekannten Tabelle gibt. Ein Trigger bei neuen Registrierungen, der so\nscheitert, zeigt sich als\n",[51,642,643],{"href":403},"\"Database error saving new user\"",[446,645],{"alt":646,"caption":647,"src":648},"Zwei Nachschlagevorgänge in einer Funktion mit search_path = ''. Der obere fragt nach invoices ohne Etage, findet eine leere Liste von Etagen zum Durchsuchen und endet an einer Plakette mit 42P01. Der untere fragt nach public.invoices, geht direkt zur Tür invoices auf der Etage public und ist abgehakt.","Mit leerem Suchpfad gibt es keine Etage zum Durchsuchen, also findet nur eine vollständige Adresse den Raum.","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fan-empty-search-path-1600x620.png",[39,650,652],{"id":651},"ursache-4-die-tabelle-ist-noch-nicht-in-diesem-projekt","Ursache 4: Die Tabelle ist noch nicht in diesem Projekt",[10,654,655],{},"Die Tabelle existiert in einer anderen Datenbank oder nur in deinem Code.",[10,657,658,659,663,664,666],{},"Ein Supabase-Konto kann mehrere Projekte enthalten, und\n",[51,660,662],{"href":661},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","ein Branch ist ein eigenes Projekt"," mit\neigener Datenbank. Eine Tabelle, die im SQL Editor des falschen Projekts angelegt\nwurde, ist ein Raum in einem anderen Gebäude.\n",[51,665,334],{"href":333},"\nzeigt, wie du die Projektreferenz in der Supabase-Adresse deiner App mit der im\nDashboard vergleichst.",[10,668,669,670,675],{},"Wenn du mit Lovable baust, such im Chat nach SQL, das du freigeben solltest. Die\n",[51,671,674],{"href":672,"rel":673},"https:\u002F\u002Fdocs.lovable.dev\u002Fintegrations\u002Fsupabase",[55],"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 Tabelle nur im\nCode, der sie liest.",[39,677,679],{"id":678},"eine-tabelle-verschieben-von-der-deine-app-abhängt","Eine Tabelle verschieben, von der deine App abhängt",[10,681,682],{},"Behalte eine Kopie der Datenbank von vor dem Verschieben, und erfahre es, wenn\nsich etwas ändert, das deine App preisgibt.",[10,684,685],{},[686,687,688,692],"strong",{},[51,689,691],{"href":690},"\u002Fsupabase-backups","Reeve Care"," bewahrt eine Kopie deiner Supabase-Datenbank auf:",[210,694,695,698,704,707,710,713],{},[213,696,697],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[213,699,700,701,703],{},"jedes Schema, das du angelegt hast, ",[14,702,67],{}," und die anderen, mit ihren Tabellen und Zeilen, wie sie vor deiner Änderung waren",[213,705,706],{},"jede Kopie wird geprüft, bevor sie zählt, indem die Zeilen in jeder Tabelle gezählt werden",[213,708,709],{},"auch deine hochgeladenen Dateien, sobald du eine Storage-Zugangsberechtigung verbindest",[213,711,712],{},"Wiederherstellung mit einem Klick, vorher wird eine Sicherheitskopie des aktuellen Stands angelegt",[213,714,715],{},"alles, was Monitor macht",[10,717,718],{},[686,719,720,724],{},[51,721,723],{"href":722},"\u002Fwebsite-monitoring","Reeve Monitor"," prüft weiter von außen:",[210,726,727,730,733,740],{},[213,728,729],{},"ob deine App erreichbar ist, jede Minute geprüft",[213,731,732],{},"der vollständige Sicherheitscheck jede Stunde, für bis zu drei Apps",[213,734,735,736,739],{},"eine Nachricht, wenn sich ein Ergebnis ",[686,737,738],{},"ändert",", sodass ein Deploy, der ändert, was deine App preisgibt, dich erreicht, ohne dass du nachsehen musst",[213,741,742],{},"ein monatlicher Bericht in klarer Sprache über das, was er gesehen hat",[39,744,746],{"id":745},"was-du-jetzt-tun-solltest","Was du jetzt tun solltest",[748,749,750],"key-takeaways",{},[210,751,752,759,762,776,786,795],{},[213,753,754,755,758],{},"Lies die Meldung: Der Name in Anführungszeichen ist das, wonach gefragt wurde, und ",[14,756,757],{},"public."," davor ist das Schema, das durchsucht wurde.",[213,760,761],{},"Vergleich den Namen mit dem Table Editor, samt Großbuchstaben. Eine Tabelle mit einem Großbuchstaben im Namen braucht in SQL doppelte Anführungszeichen.",[213,763,764,765,768,769,771,772,775],{},"Finde mit der Abfrage auf ",[14,766,767],{},"information_schema.tables"," heraus, in welchem Schema die Tabelle liegt, und ruf eine Tabelle außerhalb von ",[14,770,67],{}," mit ",[14,773,774],{},".schema('name').from(...)"," auf.",[213,777,778,779,782,783,785],{},"Bevor du ein Schema freigibst, führ die Abfrage auf ",[14,780,781],{},"pg_tables"," aus und schalte Row Level Security für jede Tabelle ein, bei der ",[14,784,507],{}," steht.",[213,787,788,789,791,792,61],{},"In einer Funktion mit ",[14,790,591],{}," schreibst du jede Tabelle als ",[14,793,794],{},"public.name",[213,796,797],{},"Prüf, dass das Projekt, das deine App aufruft, das ist, in dem du die Tabelle angelegt hast.",[10,799,800,801,804],{},"Fang bei den beiden Namen in der Meldung an, der Tabelle und dem Schema davor, denn\nsie sagen genau, nach welcher Tür auf welcher Etage gefragt wurde. Bevor du etwas\nverschiebst, umbenennst oder freigibst, das Menschen benutzen,\n",[51,802,803],{"href":690},"behalte eine Kopie der Datenbank"," von vor der Änderung.",{"title":27,"searchDepth":806,"depth":806,"links":807},3,[808,810,811,812,813,814,815,816,817],{"id":41,"depth":809,"text":42},2,{"id":195,"depth":809,"text":196},{"id":338,"depth":809,"text":339},{"id":453,"depth":809,"text":454},{"id":543,"depth":809,"text":544},{"id":584,"depth":809,"text":585},{"id":651,"depth":809,"text":652},{"id":678,"depth":809,"text":679},{"id":745,"depth":809,"text":746},"Sicherheitsgrundlagen","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcover-1200x630.png","Ein Gebäude im Querschnitt neben einem Aufzugsschacht. Der Aufzug steht im Erdgeschoss, sein Halt eine Etage höher ist eine gestrichelte bernsteinfarbene Lücke.","Supabase \"relation does not exist\" oder PGRST205: Keine Tabelle passt zu Name und Schema deiner Abfrage. Vier Prüfungen, und was eine Freigabe öffnet.",false,"md",[825,828,831,834,837],{"q":826,"a":827},"Warum sagt Supabase, dass es meine Tabelle nicht gibt?","Weil in dem Schema, das die Abfrage durchsucht hat, keine Tabelle mit genau diesem Namen liegt. Prüf vier Dinge der Reihe nach: die Großbuchstaben im Namen, das Schema, in dem die Tabelle liegt (deine App sucht in public, solange du nichts anderes sagst), das Projekt, mit dem deine App spricht, und ob die Abfrage in einer Funktion mit leerem search_path läuft, wo jede Tabelle ihr Schema davor braucht.",{"q":829,"a":830},"Was bedeutet \"the schema must be one of the following\"?","Das ist der Fehler PGRST106 im Wortlaut älterer PostgREST-Versionen. Deine App hat ein Schema angefragt, das das Projekt nicht freigibt, zum Beispiel über .schema('name'), und die Liste danach sind die freigegebenen Schemas. Neuere Versionen sagen \"Invalid schema: name\" und setzen dieselbe Liste in den Hinweis. Das Schema freizugeben behebt es, und das lohnt sich bewusst zu entscheiden.",{"q":832,"a":833},"Ist es sicher, in Supabase ein Schema freizugeben?","Erst wenn jede Tabelle darin Row Level Security eingeschaltet und eine Regel geschrieben hat. Supabases Anleitung zu eigenen Schemas gibt anon, der Rolle jedes Besuchers, der nicht angemeldet ist, vollen Zugriff auf jede Tabelle im Schema, auch auf Tabellen, die später dort angelegt werden. Seine Sicherheitsanleitung ergänzt, dass Tabellen aus dem SQL Editor Row Level Security nicht von selbst bekommen.",{"q":835,"a":836},"Spielt Groß- und Kleinschreibung bei Tabellennamen in Supabase eine Rolle?","Ja. Ein Name, der in SQL ohne doppelte Anführungszeichen geschrieben wird, wird kleingeschrieben, während der Table Editor und supabase-js die Großbuchstaben genau so behalten, wie sie geschrieben wurden. Eine Tabelle, die als Invoices angelegt wurde, schreibst du in SQL als \"Invoices\", mit Anführungszeichen, und in deiner App als .from('Invoices').",{"q":838,"a":839},"Soll ich die Tabelle stattdessen nach public verschieben?","Das Verschieben behebt die Schema-Hälfte des Fehlers und nichts an der Sicherheit: Eine Tabelle, die deine App aus dem Browser liest, braucht eine Berechtigung für die Rolle, die liest, und Row Level Security mit einer Regel, egal wo sie liegt. Eine Tabelle, die nur Servercode braucht, kann in einem nicht freigegebenen Schema bleiben, erreicht über eine Funktion in public, die genau die eine Aufgabe erledigt, die deine App braucht.","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",[842,843,844,845,846,847,848,849,850],"relation does not exist supabase","supabase relation does not exist","could not find the table in the schema cache","pgrst205","42p01","the schema must be one of the following","pgrst106","supabase schema nicht freigegeben","supabase tabelle nicht gefunden api",{},true,"\u002Fblog\u002Fsupabase-relation-does-not-exist","2026-10-23",{"title":5,"description":821},"blog\u002Fsupabase-relation-does-not-exist",[858,859,860],"Supabase \"relation does not exist\" (Postgres-Code 42P01) heißt: In den Schemas, die die Abfrage durchsucht hat, gibt es keine Tabelle und keinen View mit genau diesem Namen. Aus deiner App heißt dasselbe Problem bei einem aktuellen Projekt \"Could not find the table in the schema cache\" (PGRST205).","Prüf zuerst den Namen Buchstabe für Buchstabe, samt Großbuchstaben, dann das Schema, dann das Projekt. In einer Funktion mit leerem search_path braucht jede Tabelle ihr Schema davor: public.invoices.","Ein Schema freizugeben lässt den Fehler verschwinden und macht jede Tabelle darin über die API erreichbar. Prüf also Row Level Security auf jeder dieser Tabellen, bevor du es tust.","uwJds-aMk0DC3NSQ3iW3Rn5KaeZG3XOdRjr0wFzNSkI",[863,869,875,881,887,893,899,905,911,917,923,930,936,942,948,954,960,966,967,972,977,983,989,995,1001,1007,1013,1018,1024,1030,1036,1042,1048,1054,1060,1066,1072,1078,1084,1090,1096,1102,1108,1114,1120,1126,1130,1136,1142,1148,1154,1160,1166,1172,1178,1184,1190,1196,1202,1208,1214,1220,1225,1230,1236,1242,1248,1254,1260,1266,1272,1278,1284,1290,1296,1302,1308,1314,1319,1325,1331,1337,1343,1349,1354,1360,1366,1372,1377,1383],{"path":864,"title":865,"description":866,"published":867,"category":818,"image":868,"draft":822},"\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":870,"title":871,"description":872,"published":873,"category":818,"image":874,"draft":822},"\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":876,"title":877,"description":878,"published":879,"category":818,"image":880,"draft":822},"\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":882,"title":883,"description":884,"published":885,"category":818,"image":886,"draft":822},"\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":888,"title":889,"description":890,"published":891,"category":818,"image":892,"draft":822},"\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":894,"title":895,"description":896,"published":897,"category":818,"image":898,"draft":822},"\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":900,"title":901,"description":902,"published":903,"category":818,"image":904,"draft":822},"\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":906,"title":907,"description":908,"published":909,"category":818,"image":910,"draft":822},"\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":912,"title":913,"description":914,"published":915,"category":818,"image":916,"draft":822},"\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":918,"title":919,"description":920,"published":921,"category":818,"image":922,"draft":822},"\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":924,"title":925,"description":926,"published":927,"category":928,"image":929,"draft":822},"\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":931,"title":932,"description":933,"published":934,"category":818,"image":935,"draft":822},"\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":937,"title":938,"description":939,"published":940,"category":818,"image":941,"draft":822},"\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":943,"title":944,"description":945,"published":946,"category":818,"image":947,"draft":822},"\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":949,"title":950,"description":951,"published":952,"category":818,"image":953,"draft":822},"\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":955,"title":956,"description":957,"published":958,"category":818,"image":959,"draft":822},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","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":961,"title":962,"description":963,"published":964,"category":818,"image":965,"draft":822},"\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":853,"title":5,"description":821,"published":854,"category":818,"image":840,"draft":822},{"path":575,"title":968,"description":969,"published":970,"category":818,"image":971,"draft":822},"Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" nennt die Argumente, die deine App geschickt hat. Vergleich sie mit der Funktion.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":333,"title":973,"description":974,"published":975,"category":818,"image":976,"draft":822},"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":978,"title":979,"description":980,"published":981,"category":818,"image":982,"draft":822},"\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":984,"title":985,"description":986,"published":987,"category":818,"image":988,"draft":822},"\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":990,"title":991,"description":992,"published":993,"category":818,"image":994,"draft":822},"\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":996,"title":997,"description":998,"published":999,"category":818,"image":1000,"draft":822},"\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":1002,"title":1003,"description":1004,"published":1005,"category":818,"image":1006,"draft":822},"\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":1008,"title":1009,"description":1010,"published":1011,"category":818,"image":1012,"draft":822},"\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":403,"title":1014,"description":1015,"published":1016,"category":818,"image":1017,"draft":822},"\"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":1019,"title":1020,"description":1021,"published":1022,"category":818,"image":1023,"draft":822},"\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":1025,"title":1026,"description":1027,"published":1028,"category":818,"image":1029,"draft":822},"\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":1031,"title":1032,"description":1033,"published":1034,"category":818,"image":1035,"draft":822},"\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":1037,"title":1038,"description":1039,"published":1040,"category":818,"image":1041,"draft":822},"\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":1043,"title":1044,"description":1045,"published":1046,"category":818,"image":1047,"draft":822},"\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":1049,"title":1050,"description":1051,"published":1052,"category":818,"image":1053,"draft":822},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"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":1055,"title":1056,"description":1057,"published":1058,"category":818,"image":1059,"draft":822},"\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":1061,"title":1062,"description":1063,"published":1064,"category":818,"image":1065,"draft":822},"\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":1067,"title":1068,"description":1069,"published":1070,"category":818,"image":1071,"draft":822},"\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":1073,"title":1074,"description":1075,"published":1076,"category":818,"image":1077,"draft":822},"\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":1079,"title":1080,"description":1081,"published":1082,"category":818,"image":1083,"draft":822},"\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":1085,"title":1086,"description":1087,"published":1088,"category":818,"image":1089,"draft":822},"\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":1091,"title":1092,"description":1093,"published":1094,"category":818,"image":1095,"draft":822},"\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":1097,"title":1098,"description":1099,"published":1100,"category":818,"image":1101,"draft":822},"\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":1103,"title":1104,"description":1105,"published":1106,"category":818,"image":1107,"draft":822},"\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":1109,"title":1110,"description":1111,"published":1112,"category":928,"image":1113,"draft":822},"\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":1115,"title":1116,"description":1117,"published":1118,"category":928,"image":1119,"draft":822},"\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":1121,"title":1122,"description":1123,"published":1124,"category":928,"image":1125,"draft":822},"\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":191,"title":1127,"description":1128,"published":1124,"category":818,"image":1129,"draft":822},"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":1131,"title":1132,"description":1133,"published":1134,"category":818,"image":1135,"draft":822},"\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":1137,"title":1138,"description":1139,"published":1140,"category":818,"image":1141,"draft":822},"\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":1143,"title":1144,"description":1145,"published":1146,"category":928,"image":1147,"draft":822},"\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":1149,"title":1150,"description":1151,"published":1152,"category":818,"image":1153,"draft":822},"\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":1155,"title":1156,"description":1157,"published":1158,"category":818,"image":1159,"draft":822},"\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":1161,"title":1162,"description":1163,"published":1164,"category":818,"image":1165,"draft":822},"\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":1167,"title":1168,"description":1169,"published":1170,"category":818,"image":1171,"draft":822},"\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":1173,"title":1174,"description":1175,"published":1176,"category":818,"image":1177,"draft":822},"\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":1179,"title":1180,"description":1181,"published":1182,"category":818,"image":1183,"draft":822},"\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":1185,"title":1186,"description":1187,"published":1188,"category":818,"image":1189,"draft":822},"\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":1191,"title":1192,"description":1193,"published":1194,"category":818,"image":1195,"draft":822},"\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":1197,"title":1198,"description":1199,"published":1200,"category":928,"image":1201,"draft":822},"\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":1203,"title":1204,"description":1205,"published":1206,"category":928,"image":1207,"draft":822},"\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":1209,"title":1210,"description":1211,"published":1212,"category":928,"image":1213,"draft":822},"\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":1215,"title":1216,"description":1217,"published":1218,"category":818,"image":1219,"draft":822},"\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":511,"title":1221,"description":1222,"published":1223,"category":818,"image":1224,"draft":822},"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":516,"title":1226,"description":1227,"published":1228,"category":818,"image":1229,"draft":822},"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":1231,"title":1232,"description":1233,"published":1234,"category":818,"image":1235,"draft":822},"\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":1237,"title":1238,"description":1239,"published":1240,"category":818,"image":1241,"draft":822},"\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":1243,"title":1244,"description":1245,"published":1246,"category":818,"image":1247,"draft":822},"\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":1249,"title":1250,"description":1251,"published":1252,"category":818,"image":1253,"draft":822},"\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":1255,"title":1256,"description":1257,"published":1258,"category":818,"image":1259,"draft":822},"\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":1261,"title":1262,"description":1263,"published":1264,"category":818,"image":1265,"draft":822},"\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":1267,"title":1268,"description":1269,"published":1270,"category":818,"image":1271,"draft":822},"\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":1273,"title":1274,"description":1275,"published":1276,"category":928,"image":1277,"draft":822},"\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":1279,"title":1280,"description":1281,"published":1282,"category":818,"image":1283,"draft":822},"\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":1285,"title":1286,"description":1287,"published":1288,"category":928,"image":1289,"draft":822},"\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":1291,"title":1292,"description":1293,"published":1294,"category":818,"image":1295,"draft":822},"\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":1297,"title":1298,"description":1299,"published":1300,"category":818,"image":1301,"draft":822},"\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":1303,"title":1304,"description":1305,"published":1306,"category":818,"image":1307,"draft":822},"\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":1309,"title":1310,"description":1311,"published":1312,"category":818,"image":1313,"draft":822},"\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":661,"title":1315,"description":1316,"published":1317,"category":928,"image":1318,"draft":822},"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":1320,"title":1321,"description":1322,"published":1323,"category":928,"image":1324,"draft":822},"\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":1326,"title":1327,"description":1328,"published":1329,"category":818,"image":1330,"draft":822},"\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":1332,"title":1333,"description":1334,"published":1335,"category":818,"image":1336,"draft":822},"\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":1338,"title":1339,"description":1340,"published":1341,"category":928,"image":1342,"draft":822},"\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":1344,"title":1345,"description":1346,"published":1347,"category":818,"image":1348,"draft":822},"\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":1350,"title":1351,"description":1352,"published":1347,"category":818,"image":1353,"draft":822},"\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":1355,"title":1356,"description":1357,"published":1358,"category":818,"image":1359,"draft":822},"\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":1361,"title":1362,"description":1363,"published":1364,"category":928,"image":1365,"draft":822},"\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":1367,"title":1368,"description":1369,"published":1370,"category":818,"image":1371,"draft":822},"\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":1373,"title":1374,"description":1375,"published":1370,"category":928,"image":1376,"draft":822},"\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":1378,"title":1379,"description":1380,"published":1381,"category":928,"image":1382,"draft":822},"\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":1384,"title":1385,"description":1386,"published":1381,"category":818,"image":1387,"draft":822},"\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",1794213638729]