Supabase Fehler: "permission denied for table" (42501) beheben

11. August 2026 ca. 3 Min. Lesezeit Supabase
Inhalt 10

Deine RLS-Policies sehen gut aus – und trotzdem wirft der Supabase-Client:

permission denied for table projects
ERROR: 42501

Oder PostgREST meldet 42501 / „permission denied“. Das ist nicht dasselbe wie new row violates row-level security policy. Hier erkennst du den Unterschied und setzt die Grants richtig.

Das Problem: GRANT kommt vor RLS

Postgres prüft Rechte in Schichten. Tabellen-GRANTs für die Rolle deines Requests (anon oder authenticated) laufen vor Row Level Security. Fehlt der Privilege auf der Tabelle, stoppt Postgres mit 42501 – deine Policies werden gar nicht ausgewertet.

Typische Auslöser:

  • Tabelle per SQL / Prisma / Drizzle angelegt, ohne Grants für authenticated / anon
  • Falscher Key: Aufruf mit Anon-Key, obwohl nur authenticated Rechte hat
  • Schema/Tabelle in der API sichtbar, aber nach Migration fehlen Privileges

Siehst du dagegen new row violates row-level security policy, bist du schon an den Grants vorbei – dann Policies fixen (oder returning: 'minimal'). Siehe den RLS-Insert-Fehler-Guide.

Die Lösung: API-Rollen explizit berechtigen

Schritt 1: Fehlercode bestätigen

const { data, error } = await supabase.from('projects').select('*')
if (error) {
  console.error(error.code, error.message)
  // 42501 / "permission denied for table …" → Grants
  // "new row violates row-level security policy" → RLS-Policies
}

Schritt 2: Aktuelle Grants prüfen

SELECT grantee, privilege_type
FROM information_schema.role_table_grants
WHERE table_schema = 'public'
  AND table_name = 'projects'
ORDER BY grantee, privilege_type;

Du brauchst die Rolle, die zu deinem Client-Aufruf passt (authenticated für eingeloggte User, anon nur wenn anonymer Zugriff gewollt ist).

Schritt 3: Least Privilege gewähren

-- Eingeloggte User über Anon/Publishable-Key + User-JWT
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE public.projects TO authenticated;

-- Nur wenn anonyme Clients lesen/schreiben sollen (Writes eher selten)
-- GRANT SELECT ON TABLE public.projects TO anon;

-- Sequenzen für serial / identity Spalten
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO authenticated;

Danach RLS eingeschaltet lassen. Grants öffnen die Tür; Policies entscheiden, welche Zeilen durchkommen.

Schritt 4: API-Schema neu laden (falls nötig)

Nach neuen Tabellen oder Grant-Änderungen braucht PostgREST oft einen Schema-Reload (Dashboard → Settings → API → Reload, oder Cache-Wartezeit). Ein fehlender Grant kann auch wie „table not found in schema cache“ aussehen.

Häufige Fehler

  • Mehr RLS-Policies gegen 42501 schreiben: Policies laufen erst, wenn Grants existieren.
  • Nur sich selbst / postgres berechtigen: SQL-Editor funktioniert; der JS-Client scheitert weiter.
  • Breite Grants an anon ohne RLS: Sicherheitsloch – lieber authenticated + enge Policies.
  • Verwechslung mit Storage 403: Storage nutzt Policies auf storage.objects – siehe Storage 403 RLS beim Upload.

Checkliste

  1. ✅ Fehler ist 42501 / permission denied for table (nicht RLS violate)?
  2. ✅ Client nutzt den richtigen Key + Session?
  3. role_table_grants zeigt Rechte für authenticated (oder anon)?
  4. ✅ RLS nach dem Grant weiterhin aktiv mit echten Policies?
  5. ✅ API-Schema neu geladen, wenn die Tabelle brandneu ist?

Fazit

permission denied for table ist ein fehlender GRANT, keine kaputte RLS-Policy. API-Rolle berechtigen, RLS anlassen, danach Policies feinjustieren. Für die andere Klassiker-Meldung – Insert durch RLS blockiert – nimm den Row-Level-Security-Policy-Fix.

Verwandte Artikel

Hängst du weiter bei 42501? Schreib Tabellenname und ob du als anon oder authenticated aufrufst in einen Kommentar – ohne Secrets.

Kommentare