PostgreSQL-Fehler: permission denied for table / schema
ERROR: permission denied for table orders
-- variante a livello di schema:
ERROR: permission denied for schema app
Der Rolle, mit der Sie verbunden sind, fehlt das Recht, das die Anweisung benötigt: SELECT/INSERT/UPDATE/DELETE auf einer Tabelle, USAGE oder CREATE auf einem Schema, USAGE auf einer Sequenz. (Ältere PostgreSQL-Versionen formulieren das erste als "permission denied for relation".) Die Lösung ist immer ein GRANT — der interessante Teil ist, warum der Grant fehlte.
Was dieser Fehler bedeutet
PostgreSQL-Berechtigungen sind pro Objekt und kaskadieren nicht: um app.orders zu lesen, brauchen Sie sowohl USAGE auf dem Schema app als auch SELECT auf der Tabelle. Eigentümer halten implizit alle Rechte auf ihren Objekten — was genau der Grund ist, warum alles in der Entwicklung funktioniert (wo die App als Eigentümer verbindet) und in der Produktion bricht (wo sie es nicht tut).
Zwei benachbarte Varianten, die man kennen sollte: permission denied for sequence orders_id_seq bedeutet, die Rolle darf die Tabelle schreiben, aber keine IDs aus ihrer Sequenz ziehen; permission denied for schema public begann mit PostgreSQL 15 breit aufzutauchen, das aufhörte, jedem Benutzer standardmäßig das Erstellen von Objekten in public zu erlauben.
Häufige Ursachen
- Objekte von einer anderen Rolle erstellt. Migrationen laufen als
migratoroder einem Admin; die App verbindet alsapp_user; niemand hatapp_useretwas auf den neuen Tabellen erteilt. - Grants gelten nicht rückwirkend nach vorn:
GRANT ... ON ALL TABLES IN SCHEMAdeckt nur bestehende Tabellen ab. Nächste Woche erstellte Tabellen sind nicht abgedeckt — dafür istALTER DEFAULT PRIVILEGESda. - Die
ALTER DEFAULT PRIVILEGES-Falle: es gilt nur für Objekte, die von der Rolle erstellt werden, für die es gesetzt wurde. Es als Sie selbst zu setzen, während Migrationen als eine andere Rolle laufen, bewirkt nichts. - Fehlendes Schema-
USAGE— Tabellen-Grants sind nutzlos, wenn die Rolle das Schema nicht durchqueren kann. - PostgreSQL 15+:
CREATEauf dem Schemapublicwird nicht mehr jedem erteilt; Tools, die zuvor "einfach funktionierten", beginnen nach einem Upgrade zu scheitern.
So diagnostizieren Sie ihn
SELECT current_user; -- wer Sie wirklich sind (Vorsicht bei Poolern)
\dp orders -- Rechte und Eigentümer der Tabelle
\dn+ -- Rechte auf den Schemas
SELECT has_table_privilege('app_user', 'app.orders', 'SELECT');
Lesen Sie die \dp-Ausgabe gnadenlos: eine leere Spalte "Access privileges" bedeutet, nur der Eigentümer hat Zugriff. Und prüfen Sie, wer der Eigentümer ist — das erklärt meist, wie die Situation entstand.
So beheben Sie ihn
-- Das typische Minimalset für eine Anwendungsrolle:
GRANT USAGE ON SCHEMA app TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA app TO app_user;
-- Und für ZUKÜNFTIGE Tabellen, die von der Migrations-Rolle erstellt werden:
ALTER DEFAULT PRIVILEGES FOR ROLE migrator IN SCHEMA app
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
ALTER DEFAULT PRIVILEGES FOR ROLE migrator IN SCHEMA app
GRANT USAGE, SELECT ON SEQUENCES TO app_user;
-- PostgreSQL 15+, falls Objekte in public erstellt werden müssen:
GRANT CREATE ON SCHEMA public TO app_user;
- Beachten Sie das
FOR ROLE migrator: Default-Privileges müssen an die Rolle gebunden werden, die die Objekte erstellt. - Strukturelle Alternative, die viele Teams übernehmen: alle Objekte einer dedizierten
app_owner-Rolle gehören lassen, Migrationen als diese ausführen und der Laufzeit-Rolle nur das erteilen, was sie braucht.
