Référence des erreurs PostgreSQL
Les erreurs que PostgreSQL vous envoie vraiment en production, une page chacune : ce que signifie le message, les causes typiques, comment la diagnostiquer et comment la corriger — avec de vraies commandes, sans détour.
Connexions et authentification
too many clients
max_connections est épuisé. Comment voir qui détient les slots, et pourquoi la vraie solution est généralement un pooler de connexions, pas une limite plus grande.
Connexionsconnection refused
La connexion TCP n'a jamais atteint PostgreSQL du tout. Serveur arrêté, mauvais port, listen_addresses, pare-feu ou réseau Docker — dans cet ordre.
SQLSTATE 28P01password authentication failed
Parfois le mot de passe est vraiment erroné. Les autres fois : le rôle n'a pas de mot de passe, une incohérence SCRAM/md5, ou un URI qui avait besoin d'un percent-encoding.
SQLSTATE 28000no pg_hba.conf entry
Le serveur est joignable mais aucune règle pg_hba.conf ne correspond à votre combinaison (hôte, base, utilisateur, SSL). L'erreur vous dit exactement laquelle.
SQLSTATE 3D000database does not exist
Souvent la base nommée dans l'erreur est votre propre nom d'utilisateur — la valeur par défaut de psql quand vous n'en spécifiez pas. Ou vous êtes carrément sur le mauvais port.
SQLSTATE 28000role does not exist
Installation neuve, et PostgreSQL ne sait pas qui est « ubuntu ». Pourquoi le nom d'utilisateur OS apparaît, et comment amorcer les rôles correctement.
SQLSTATE 08006server closed the connection
Soit le processus serveur est mort (le journal le dira) soit un pare-feu/NAT a silencieusement coupé une connexion inactive (le journal sera muet). Vérifiez d'abord le journal.
Concurrence et verrous
deadlock detected
Deux transactions détiennent chacune un verrou dont l'autre a besoin. Pourquoi cela arrive, comment lire les lignes DETAIL, et les habitudes d'ordonnancement des verrous qui l'évitent.
SQLSTATE 40001could not serialize access
Repeatable Read ou Serializable a refusé de faire comme si deux transactions en conflit s'étaient toutes deux produites. Pas un bug — mais votre code doit réessayer.
SQLSTATE 25P02current transaction is aborted
Jamais le vrai problème : une instruction antérieure dans la transaction a déjà échoué, et PostgreSQL refuse tout jusqu'à ce que vous fassiez un ROLLBACK.
SQLSTATE 55P03lock timeout
L'instruction a renoncé à attendre un verrou — parce que quelqu'un a judicieusement défini lock_timeout. Trouvez le bloqueur, et conservez le motif fail-fast.
SQLSTATE 40001conflict with recovery
Uniquement sur les réplicas : le rejeu WAL devait supprimer des versions de ligne que votre requête utilisait encore. La solution est un compromis que vous devez choisir consciemment.
Contraintes et intégrité des données
duplicate key value
Une contrainte d'unicité a fait son travail. La question intéressante est pourquoi : une course à l'insertion, une séquence laissée en arrière par un import, ou un client qui réessaie.
SQLSTATE 23502not-null violation
Une colonne NOT NULL se retrouverait vide. La variante sournoise : votre ORM envoie un NULL explicite, qui écrase le DEFAULT de la colonne.
SQLSTATE 23503foreign key violation
Deux directions, une contrainte : un enfant pointant vers un parent absent, ou un parent en cours de suppression alors que des enfants le référencent encore.
SQLSTATE 22P02invalid input syntax
Une valeur texte n'a pas pu être analysée comme le type cible. Généralement un cast sur des données sales, une chaîne vide là où on attendait un nombre, ou un en-tête CSV.
SQLSTATE 22001value too long
Des données ont dépassé une limite varchar(n) et PostgreSQL refuse de tronquer silencieusement. Souvent la vraie solution est de remettre en question le (n) lui-même.
SQLSTATE 22012division by zero
Un dénominateur a atteint zéro — généralement un groupe vide dans une agrégation. La solution en une ligne à mémoriser : NULLIF(denominator, 0).
SQLSTATE 42P10no constraint matching ON CONFLICT
ON CONFLICT a besoin d'un index unique sur exactement les colonnes (ou l'expression, ou le prédicat partiel) que vous avez nommées. Un index ordinaire ne compte pas.
SQL, types et schéma
permission denied
Votre rôle n'a pas un privilège — souvent parce que les tables ont été créées par le rôle de migration et que personne n'a accordé quoi que ce soit dessus au rôle applicatif.
SQLSTATE 42P01relation does not exist
La table existe — vous ne regardez simplement pas là où PostgreSQL regarde. search_path, identifiants entre guillemets et mauvaise base, dans cet ordre.
SQLSTATE 42703column does not exist
Trois pièges causent la plupart de ces cas : des colonnes camelCase nécessitant des guillemets, des « chaînes » entre guillemets doubles (ce sont des identifiants !), et des alias dans WHERE.
SQLSTATE 42601syntax error at or near
Le caret pointe là où le parseur a abandonné — l'erreur est généralement dessus ou juste avant. Les mots réservés et la syntaxe MySQL sont en tête de liste.
SQLSTATE 42883function does not exist
Lisez-le ainsi : aucune fonction de ce nom avec ces types d'arguments. La fonction existe généralement — ce sont vos arguments qui sont du mauvais type.
SQLSTATE 42803must appear in GROUP BY
Vous avez sélectionné une colonne qui n'est ni groupée ni agrégée. Souvent la vraie intention est « la dernière ligne par groupe » — ce qui veut DISTINCT ON, pas GROUP BY.
SQLSTATE 21000more than one row returned
Une sous-requête scalaire promettait au plus une ligne et en a livré plusieurs. Soit vous vouliez IN — soit vos données ont des doublons qu'elles ne devraient pas avoir.
Ressources et exploitation
statement timeout
Une requête a dépassé statement_timeout. Déterminez si elle était lente, bloquée sur un verrou, ou si le timeout était défini quelque part que vous aviez oublié.
SQLSTATE 53200out of shared memory
Malgré son nom effrayant, c'est presque toujours la table de verrous partagée qui se remplit — typiquement une transaction touchant des milliers de partitions.
SQLSTATE 53100no space left on device
Le disque est plein — et sur les hôtes PostgreSQL le coupable est souvent du WAL retenu par un slot de réplication mort. Règle numéro un : ne jamais supprimer à la main dans le répertoire de données.
Opérationswraparound protection
Le frein d'urgence de MVCC : identifiants de transaction presque épuisés parce que le gel a pris du retard. Trouvez ce qui a bloqué vacuum, puis laissez-le rattraper.
Trouver le SQLSTATE d'une erreur
Chaque erreur PostgreSQL porte un code SQLSTATE de cinq caractères, plus stable que le texte du message (et c'est ce que votre driver expose pour la gestion programmatique). Dans psql, exécutez \set VERBOSITY verbose et le code est affiché avec chaque erreur ; dans le code applicatif, lisez le champ SQLSTATE de l'objet erreur de votre driver. Les pages ci-dessus indiquent le SQLSTATE correspondant à chaque erreur.
