[{"data":1,"prerenderedAt":467},["ShallowReactive",2],{"blog-de-new-row-violates-row-level-security-policy":3},{"id":4,"title":5,"body":6,"category":425,"cover":426,"coverAlt":427,"description":428,"draft":429,"extension":430,"faq":431,"image":447,"keywords":448,"meta":455,"navigation":456,"ogTitle":457,"path":458,"published":459,"seo":460,"stem":461,"tldr":462,"updated":459,"__hash__":466},"blog_de\u002Fblog\u002Fnew-row-violates-row-level-security-policy.md","New row violates row-level security policy in Supabase: was jetzt?",{"type":7,"value":8,"toc":414},"minimark",[9,13,24,32,37,40,47,50,63,66,70,73,76,79,83,86,96,99,182,188,195,223,231,235,238,241,247,254,262,266,269,275,285,298,302,305,310,313,322,337,351,359,363,401],[10,11,12],"p",{},"Irgendetwas hat dir geraten, Row Level Security anzuschalten. Der Advisor in\ndeinem Supabase-Dashboard, ein Scan-Ergebnis, eine Checkliste, jemand in einem\nDiscord. Du hast es angeschaltet. Jetzt kann deine App überhaupt nichts mehr\nspeichern. Jeder Versuch kommt mit der Meldung zurück, dass a new row violates\nrow-level security policy:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","new row violates row-level security policy for table \"profiles\"\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26,27,31],{},"Hier ist der Punkt, den Anleitung um Anleitung falsch darstellt: ",[28,29,30],"strong",{},"Die Antwort,\ndie diesen Fehler in zehn Sekunden beendet, macht genau das rückgängig, was du\ngerade angeschaltet hast."," Sie ist das erste Ergebnis, das du findest, sie\nwirkt sofort, und sie lässt die Tabelle exakt dort, wo sie war, bevor dir\njemand geraten hat, sie in Ordnung zu bringen.",[33,34,36],"h2",{"id":35},"was-new-row-violates-row-level-security-policy-bedeutet","Was \"new row violates row-level security policy\" bedeutet",[10,38,39],{},"Deine Datenbank sollte eine Zeile speichern, hat die Regeln dieser Tabelle\ngeprüft, keine gefunden, die genau diese Zeile erlaubt, und abgelehnt.",[10,41,42,43,46],{},"Das ist die ganze Meldung. Nichts ist beschädigt und nichts ist verloren: Die\nZeile wurde nie gespeichert, und der Rest der Tabelle steht genau so da wie vor\neiner Minute. Der Wortlaut kommt von Postgres, der Datenbank-Engine, auf der\nSupabase läuft, und deshalb liest er sich nach Maschine statt nach irgendetwas,\ndas dein Builder geschrieben hat. Supabase reicht ihn mit seiner Nummer weiter,\n",[21,44,45],{},"42501",".",[10,48,49],{},"Was die Meldung dir nicht sagt, ist, welche Regel gefehlt hat. Ein Satz deckt\ndrei verschiedene Situationen ab, und dir zu sagen, in welcher du steckst, würde\ndemjenigen deine Regeln beschreiben, der den Fehler ausgelöst hat:",[51,52,53,57,60],"ul",{},[54,55,56],"li",{},"Die Tabelle hat Row Level Security an und gar keine Regeln geschrieben.",[54,58,59],{},"Sie hat eine Regel, und die handelt nur vom Lesen.",[54,61,62],{},"Sie hat eine Regel zum Schreiben, und die Zeile, die du geschickt hast, erfüllt sie nicht.",[10,64,65],{},"Alle drei geben dieselbe Zeile aus. Die zweite ist die häufige bei einer frisch\ngestarteten App, wo eine Regel ergänzt wurde, damit die Bildschirme wieder\nlaufen, und vom Speichern nie die Rede war.",[33,67,69],{"id":68},"warum-er-genau-beim-anschalten-von-row-level-security-auftauchte","Warum er genau beim Anschalten von Row Level Security auftauchte",[10,71,72],{},"Weil Anschalten alles ablehnt, bis eine Regel etwas anderes sagt, und deine\neigene App zu allem dazugehört.",[10,74,75],{},"Das ist der Ablauf, den fast jeder durchmacht. Du schaltest die Einstellung an.\nDie Bildschirme bleiben leer, denn ohne geschriebene Regeln gibt die Datenbank\njetzt niemandem mehr Zeilen heraus, deiner App eingeschlossen. Du ergänzt eine\nRegel, damit die Listen zurückkommen, meist die erste, die ein Suchergebnis oder\ndein Builder vorschlägt. Die Bildschirme füllen sich. Und beim ersten Mal, wenn\njemand auf Speichern drückt, erscheint dieser Fehler, bei einer Tabelle, die du\nfür erledigt gehalten hast.",[10,77,78],{},"In diesem Ablauf ist nichts schiefgegangen. Die Regel, die du ergänzt hast,\nhandelte vom Lesen, und Speichern ist eine andere Frage, die bis dahin niemand\ngestellt hatte.",[33,80,82],{"id":81},"eine-regel-hat-zwei-hälften-und-nur-eine-handelt-vom-lesen","Eine Regel hat zwei Hälften, und nur eine handelt vom Lesen",[10,84,85],{},"Eine Policy ist eine Bedingung, und worauf die Datenbank diese Bedingung\nanwendet, hängt davon ab, worum du sie gebeten hast.",[10,87,88,91,92,95],{},[21,89,90],{},"USING"," wird auf Zeilen angewendet, die schon in der Tabelle liegen. Es\nentscheidet, welche du sehen, ändern oder entfernen darfst. ",[21,93,94],{},"WITH CHECK"," wird\nauf die Zeile angewendet, die du anlegen willst, bevor sie irgendwo existiert.\nEs entscheidet, ob diese Zeile überhaupt entstehen darf.",[10,97,98],{},"Die zweite Hälfte ist der Teil, der Menschen überrascht, denn sie ist eine Regel\nüber etwas, das noch nicht da ist.",[100,101,102,118],"table",{},[103,104,105],"thead",{},[106,107,108,112,115],"tr",{},[109,110,111],"th",{},"Deine App möchte",[109,113,114],{},"Geprüft an Zeilen, die schon in der Tabelle stehen",[109,116,117],{},"Geprüft an der Zeile, die geschrieben wird",[119,120,121,138,152,168],"tbody",{},[106,122,123,131,135],{},[124,125,126,127,130],"td",{},"lesen (",[21,128,129],{},"select",")",[124,132,133],{},[21,134,90],{},[124,136,137],{},"nichts zu prüfen",[106,139,140,146,148],{},[124,141,142,143,130],{},"eine neue Zeile speichern (",[21,144,145],{},"insert",[124,147,137],{},[124,149,150],{},[21,151,94],{},[106,153,154,160,164],{},[124,155,156,157,130],{},"eine Zeile ändern (",[21,158,159],{},"update",[124,161,162],{},[21,163,90],{},[124,165,166],{},[21,167,94],{},[106,169,170,176,180],{},[124,171,172,173,130],{},"eine Zeile entfernen (",[21,174,175],{},"delete",[124,177,178],{},[21,179,90],{},[124,181,137],{},[183,184],"diagram",{"alt":185,"caption":186,"src":187},"Eine Regel zweimal gezeichnet. Links zeigt sie auf einen Stapel Zeilen, die schon in einer Tabelle liegen, und zwei davon kommen zurück. Rechts zeigt dieselbe Regel auf eine einzelne Zeile, die als Umriss gezeichnet ist und draußen wartet, und sie wird abgewiesen.","Dieselbe Bedingung, auf zwei verschiedene Dinge gerichtet. Beim Lesen wird sie zu Zeilen befragt, die es gibt; beim Speichern zu einer Zeile, die es noch nicht gibt.","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fusing-and-with-check-1600x780.png",[10,189,190,191,194],{},"Eine Policy mit ",[21,192,193],{},"FOR SELECT"," trägt immer nur die erste Hälfte, denn beim Lesen\ngibt es keine neue Zeile zu prüfen. Sie kann also nie ein Speichern erlauben, so\ngroßzügig sie auch aussieht. Das ist der ganze Bruch, und er erklärt, warum dein\nLesen sich erholt hat und dein Schreiben nicht.",[196,197,199],"callout",{"type":198},"warn",[10,200,201,207,208,210,211,213,214,216,217,219,220,222],{},[28,202,190,203,206],{},[21,204,205],{},"FOR ALL"," verhält sich anders, und zwar leise."," Schreibst du\neine mit einer ",[21,209,90],{},"-Bedingung und ohne ",[21,212,94],{},", wendet Postgres dieselbe\n",[21,215,90],{},"-Bedingung auch auf neue Zeilen an. Eine ",[21,218,205],{},"-Regel, die sagt, dass\nZeilen ihren Besitzern gehören, lehnt also ein Speichern ab, bei dem der\nBesitzer nicht passt, ohne dass irgendwo in dem, was du geschrieben hast, ein\n",[21,221,94],{}," steht. Nützlich, wenn du es so gemeint hast. Verwirrend, wenn du\neine Regel liest, die jemand anderes eingefügt hat.",[10,224,225,226,46],{},"Wenn du das lieber von außen sehen möchtest: Unser kostenloser Scan fragt deine\nDatenbank live, was ein Fremder schon jetzt aus ihr lesen kann, ohne Konto und\nin rund 20 Sekunden: ",[227,228,230],"a",{"href":229},"\u002F#scan","App scannen",[33,232,234],{"id":233},"die-lösung-die-den-fehler-beendet-und-was-sie-kostet","Die Lösung, die den Fehler beendet, und was sie kostet",[10,236,237],{},"Am schnellsten verschwindet er mit einer Regel, die jedes Schreiben von jedem\nerlaubt, und genau deshalb ist sie fast überall die oberste Antwort.",[10,239,240],{},"Sie kommt meist so daher:",[14,242,245],{"className":243,"code":244,"language":19},[17],"CREATE POLICY \"Enable insert for all users\"\n  ON public.profiles\n  FOR INSERT\n  WITH CHECK (true);\n",[21,246,244],{"__ignoreMap":23},[10,248,249,250,253],{},"Jede Zeile erfüllt ",[21,251,252],{},"true",", also ist jedes Speichern erlaubt, von deiner App und\nvon jedem anderen, der den Schlüssel hat, der darin mitgeliefert wird. Row Level\nSecurity wieder abzuschalten leistet dasselbe noch gründlicher.",[10,255,256,257,261],{},"Beides funktioniert. Beides lässt dich dort, wo du vor dem Hinweis des Advisors\nwarst, und danach zeigt keines von beiden noch an, dass etwas offen ist, denn\ndeine App verhält sich in allen vier Kombinationen aus Einstellung und Regel\ngleich. Eine Tabelle kann angeschaltet sein, eine gültige Policy tragen, ein\ngrünes Abzeichen im Dashboard zeigen und ihre Zeilen trotzdem an einen Fremden\nherausgeben. Das ist\n",[227,258,260],{"href":259},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","die andere Hälfte dieses Problems",",\nund sie ist es wert, gelesen zu werden, bevor du irgendetwas einfügst.",[33,263,265],{"id":264},"die-regel-die-deine-app-speichern-lässt-und-nur-deine-app","Die Regel, die deine App speichern lässt, und nur deine App",[10,267,268],{},"Benenne, wem die Zeile gehört, und vergleiche das mit dem, der gerade fragt:",[14,270,273],{"className":271,"code":272,"language":19},[17],"CREATE POLICY \"Users insert their own rows\"\n  ON public.profiles\n  FOR INSERT\n  TO authenticated\n  WITH CHECK (auth.uid() = user_id);\n",[21,274,272],{"__ignoreMap":23},[10,276,277,280,281,284],{},[21,278,279],{},"auth.uid()"," ist, wer angemeldet ist und die Anfrage stellt. ",[21,282,283],{},"user_id"," ist die\nSpalte auf der Zeile, die sagt, wem sie gehört. Stimmen die beiden überein, wird\ndie Zeile gespeichert. Tun sie es nicht, oder ist niemand angemeldet, wird sie\nabgelehnt, und wer abgelehnt wird, sieht dieselbe Meldung, die du gerade\nanschaust.",[10,286,287,288,291,292,294,295,297],{},"Zwei Details in dieser Regel verdienen ihren Platz. ",[21,289,290],{},"TO authenticated"," heißt,\ndass die Regel für angemeldete Besucher gilt; lässt du es weg, gilt die Policy\nfür alle, Fremde eingeschlossen. Und deine App muss die Spalte ",[21,293,283],{},"\ntatsächlich mitschicken, denn eine Regel, die ",[21,296,279],{}," mit einem leer\nangekommenen Wert vergleicht, kann nie übereinstimmen.",[33,299,301],{"id":300},"wenn-die-regel-stimmt-und-der-fehler-trotzdem-kommt","Wenn die Regel stimmt und der Fehler trotzdem kommt",[10,303,304],{},"Schau, wer angemeldet war, bevor du dir die Policy noch einmal ansiehst.",[183,306],{"alt":307,"caption":308,"src":309},"Drei Tabellen nebeneinander. Bei jeder kommt eine als Umriss gezeichnete Zeile von oben an, und ihr Pfeil bleibt kurz vor der Regel darunter stehen. Die Regel der ersten Tabelle ist ein leerer gestrichelter Umriss, die der zweiten trägt select, die der dritten insert. Ein Streifen unter allen dreien trägt den Code 42501.","Drei verschiedene Ursachen, die dich als ein Satz erreichen. Der Code 42501 ist bei allen dreien derselbe, und deshalb kann die Meldung allein dir nicht sagen, in welcher du steckst.","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fthree-causes-one-message-1600x700.png",[10,311,312],{},"Drei Erklärungen decken das meiste ab, was übrig bleibt:",[10,314,315,318,319,321],{},[28,316,317],{},"Niemand ist angemeldet."," ",[21,320,279],{}," kommt bei einem Besucher, der sich nie\nangemeldet hat, leer zurück, also kann eine Regel, die es mit einer\nBesitzerspalte vergleicht, nicht übereinstimmen. Bei einem\nRegistrierungsformular, einer Warteliste oder einem Kontaktformular ist das\nnormal, und die brauchen eine eigene Regel, die beschreibt, was ein Fremder\nergänzen darf.",[10,323,324,327,328,330,331,333,334,336],{},[28,325,326],{},"Die Besitzerspalte kommt nie an."," Deine Regel vergleicht ",[21,329,279],{}," mit\n",[21,332,283],{},", und deine App schickt alles außer ",[21,335,283],{},". Der Vergleich läuft\ngegen eine Leerstelle und scheitert jedes Mal.",[10,338,339,342,343,346,347,350],{},[28,340,341],{},"Der Schreibvorgang geht an Storage."," Datei-Uploads landen in Supabase\nStorage, das eigene Policies auf ",[21,344,345],{},"storage.objects"," führt statt auf deiner\nTabelle. Eine Regel auf ",[21,348,349],{},"profiles"," sagt nichts über eine Datei.",[10,352,353,354,358],{},"Es gibt eine vierte Erklärung, und die schließt man am besten früh aus: Wenn das\nSpeichern in der Vorschau deines Builders klappt und auf deiner Live-Seite\nscheitert, benutzen beide nicht denselben Schlüssel. Ein geheimer Schlüssel\nignoriert jede Regel, die du geschrieben hast, dafür ist er gedacht. Eine App,\ndie nur speichert, solange ein geheimer Schlüssel im Spiel ist, ist eine App,\nderen Regeln nie wirklich geprüft wurden.\n",[227,355,357],{"href":356},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Welche API-Schlüssel im Frontend sicher sind","\nzeigt, wie du den einen vom anderen unterscheidest.",[33,360,362],{"id":361},"was-du-heute-tun-solltest","Was du heute tun solltest",[364,365,366],"key-takeaways",{},[51,367,368,371,377,391,394],{},[54,369,370],{},"Lies den Fehler als Ablehnung statt als Defekt. Der Schreibvorgang hat nicht stattgefunden, die Tabelle ist unverändert, und nichts muss wiederhergestellt werden.",[54,372,373,374,376],{},"Prüfe, ob die Tabelle überhaupt eine Policy zum Schreiben hat. Eine Regel mit ",[21,375,193],{}," hat deine Bildschirme repariert und nichts über das Speichern gesagt.",[54,378,379,380,383,384,386,387,390],{},"Ergänze eine Policy ",[21,381,382],{},"FOR INSERT",", deren ",[21,385,94],{},"-Bedingung den Besitzer der Zeile benennt, und ergänze die ",[21,388,389],{},"TO","-Klausel, die du gemeint hast.",[54,392,393],{},"Stelle sicher, dass deine App die Besitzerspalte wirklich mitschickt, und versuche das Speichern dann angemeldet erneut.",[54,395,396,397,400],{},"Lass ",[21,398,399],{},"WITH CHECK (true)"," für Tabellen stehen, deren Inhalt dir auf einer öffentlichen Seite recht wäre. Bei allem, in dem ein Mensch vorkommt, nimm dir die zwei Minuten.",[10,402,403,404,408,409,413],{},"Fang mit der Tabelle an, aus der der Fehler kam, und prüfe jede andere Tabelle,\nbei der du die Einstellung am selben Nachmittag angeschaltet hast. Die\n",[227,405,407],{"href":406},"\u002Fchecklist","10-Minuten-Sicherheitscheckliste"," deckt ab, was bei einer frisch\ngestarteten App sonst noch offen zu bleiben pflegt, und der\n",[227,410,412],{"href":411},"\u002Fis-your-supabase-app-safe","Supabase-Sicherheitsleitfaden"," geht durch, woran\nein Fremder sonst noch herankommt.",{"title":23,"searchDepth":415,"depth":415,"links":416},3,[417,419,420,421,422,423,424],{"id":35,"depth":418,"text":36},2,{"id":68,"depth":418,"text":69},{"id":81,"depth":418,"text":82},{"id":233,"depth":418,"text":234},{"id":264,"depth":418,"text":265},{"id":300,"depth":418,"text":301},{"id":361,"depth":418,"text":362},"Sicherheitsgrundlagen","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcover-1200x630.png","Ein Stapel Zeilen in einer Tabelle, daneben eine Zeile, die draußen wartet, nur als Umriss gezeichnet, weil sie noch nicht hereindurfte.","\"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.",false,"md",[432,435,438,441,444],{"q":433,"a":434},"Was bedeutet \"new row violates row-level security policy\"?","Es bedeutet, dass deine Datenbank eine Zeile speichern sollte, die Regeln dieser Tabelle geprüft hat und keine gefunden hat, die diese Zeile erlaubt. Also hat sie den Schreibvorgang abgelehnt. Nichts ist verloren und nichts ist kaputt, denn die Zeile wurde nie gespeichert und der Rest der Tabelle ist unberührt. Die Meldung kommt von Postgres, der Datenbank-Engine, auf der Supabase läuft, und sie trägt den Code 42501. Was sie bewusst nicht sagt, ist, welche Regel gefehlt hat, denn das würde demjenigen deine Regeln beschreiben, der den Fehler ausgelöst hat.",{"q":436,"a":437},"Ich habe eine Policy ergänzt und Lesen funktioniert. Warum scheitert Speichern trotzdem?","Weil eine Policy zum Lesen nichts über das Schreiben sagt. Eine Regel hat eine USING-Hälfte, die die Datenbank auf Zeilen anwendet, die schon in der Tabelle stehen, und eine WITH CHECK-Hälfte, die sie auf die Zeile anwendet, die du anlegen willst. Eine Policy mit FOR SELECT hat immer nur die erste, denn beim Lesen gibt es keine neue Zeile zu prüfen. Deine Bildschirme füllen sich wieder und das erste Speichern scheitert weiterhin. Ergänze eine zweite Policy FOR INSERT mit einer WITH CHECK-Bedingung.",{"q":439,"a":440},"Soll ich Row Level Security einfach abschalten, damit das weggeht?","Das beendet den Fehler, und es lässt jede Zeile dieser Tabelle für jeden lesbar, der den Schlüssel hat, der in deiner App mitgeliefert wird. Deine App läuft in beiden Fällen, also sagt dir danach nichts mehr, welche der beiden Varianten du gewählt hast. Wenn in der Tabelle Menschen, Bestellungen oder Nachrichten stehen, sind die zwei Minuten für eine echte Regel der Unterschied zwischen einer privaten und einer öffentlichen Tabelle.",{"q":442,"a":443},"Meine Policy sieht richtig aus und Inserts scheitern trotzdem. Was kann es sonst sein?","Drei Dinge erklären die meisten Fälle. Niemand ist angemeldet, also ist auth.uid() leer und eine Regel, die es mit einer Besitzerspalte vergleicht, kann nie übereinstimmen, was bei einem Registrierungs- oder Kontaktformular normal ist. Oder deine App schickt die Besitzerspalte gar nicht mit, sodass die Regel gegen einen leeren Wert vergleicht. Oder der Schreibvorgang geht in Supabase Storage statt in eine Tabelle, und Storage führt eigene Policies auf storage.objects.",{"q":445,"a":446},"Heißt dieser Fehler, dass jemand meine App angegriffen hat?","Fast nie. Bei einer frisch gestarteten App ist es fast immer deine eigene App, die abgewiesen wird, weil Row Level Security angeschaltet wurde, bevor eine Regel für deine eigenen Schreibvorgänge existierte. Trotzdem lohnt es sich, sie zu lesen statt sie wegzuklicken: Dieselbe Meldung erscheint, wenn eine Anfrage abgewiesen wird, die gar nicht in diese Tabelle schreiben sollte, und an der Meldung allein kannst du beides nicht unterscheiden.","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",[449,450,451,452,453,454],"new row violates row-level security policy","supabase rls insert policy","rls blockiert insert","supabase with check policy","row level security supabase aktivieren","row level security fehler",{},true,"New row violates row-level security policy","\u002Fblog\u002Fnew-row-violates-row-level-security-policy","2026-08-27",{"title":5,"description":428},"blog\u002Fnew-row-violates-row-level-security-policy",[463,464,465],"New row violates row-level security policy heißt: Deine Datenbank hat die Regeln dieser Tabelle geprüft und keine gefunden, die die Zeile erlaubt, die du speichern wolltest. Sie hat den Schreibvorgang abgelehnt und die Tabelle so gelassen, wie sie war.","Eine Meldung deckt drei verschiedene Situationen ab: gar keine Regeln, eine Regel, die nur vom Lesen handelt, oder eine Regel zum Schreiben, die deine Zeile nicht erfüllt.","Die Antwort ganz oben in jeder Suche beendet den Fehler, indem sie jedes Schreiben von jedem erlaubt. Die Regel, die du eigentlich willst, kostet rund zwei Minuten mehr.","OsHNU1fM7HgpI3Jz3S_kjliHsqxicEO97DYtThKo2Vs",1787826048205]