Erreur PostgreSQL : permission denied for table / schema

ERROR:  permission denied for table orders

-- variante a livello di schema:
ERROR:  permission denied for schema app

Le rôle sous lequel vous êtes connecté n'a pas le privilège dont l'instruction a besoin : SELECT/INSERT/UPDATE/DELETE sur une table, USAGE ou CREATE sur un schéma, USAGE sur une séquence. (Les versions plus anciennes de PostgreSQL formulent la première comme « permission denied for relation ».) La solution est toujours un GRANT — la partie intéressante est pourquoi le grant manquait.

Ce que signifie cette erreur

Les privilèges de PostgreSQL sont par objet et ne se propagent pas en cascade : pour lire app.orders vous avez besoin à la fois de USAGE sur le schéma app et de SELECT sur la table. Les propriétaires détiennent implicitement tous les privilèges sur leurs objets — ce qui est exactement pourquoi tout fonctionne en développement (où l'application se connecte en tant que propriétaire) et casse en production (où ce n'est pas le cas).

Deux variantes voisines à reconnaître : permission denied for sequence orders_id_seq signifie que le rôle peut écrire la table mais pas tirer d'ID de sa séquence ; permission denied for schema public a commencé à apparaître largement avec PostgreSQL 15, qui a cessé de laisser chaque utilisateur créer des objets dans public par défaut.

Causes fréquentes

Comment la diagnostiquer

SELECT current_user;                -- qui vous êtes vraiment (attention aux poolers)

\dp orders                          -- privilèges et propriétaire de la table
\dn+                                -- privilèges sur les schémas

SELECT has_table_privilege('app_user', 'app.orders', 'SELECT');

Lisez la sortie de \dp sans pitié : une colonne « Access privileges » vide signifie que seul le propriétaire a accès. Et vérifiez qui est le propriétaire — cela explique généralement comment la situation est survenue.

Comment la corriger

-- Le jeu minimal typique pour un rôle applicatif :
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;

-- Et pour les tables FUTURES créées par le rôle des migrations :
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+, s'il faut créer des objets dans public :
GRANT CREATE ON SCHEMA public TO app_user;