PostgreSQL-Fehlerreferenz
Die Fehler, die PostgreSQL Ihnen in der Produktion wirklich um die Ohren wirft, je eine Seite: was die Meldung bedeutet, die typischen Ursachen, wie man ihn diagnostiziert und behebt — mit echten Befehlen, ohne Geschwafel.
Verbindungen & Authentifizierung
too many clients
max_connections ist erschöpft. Wie Sie sehen, wer die Slots hält, und warum die eigentliche Lösung meist ein Connection-Pooler ist, nicht ein höheres Limit.
Verbindungenconnection refused
Die TCP-Verbindung erreichte PostgreSQL überhaupt nicht. Server aus, falscher Port, listen_addresses, Firewall oder Docker-Netzwerk — in dieser Reihenfolge.
SQLSTATE 28P01password authentication failed
Manchmal ist das Passwort wirklich falsch. Die anderen Male: die Rolle hat kein Passwort, SCRAM/md5-Mismatch oder eine URI, die Prozent-Kodierung gebraucht hätte.
SQLSTATE 28000no pg_hba.conf entry
Der Server ist erreichbar, aber keine pg_hba.conf-Regel trifft Ihre Kombination aus (Host, Datenbank, Benutzer, SSL). Der Fehler sagt Ihnen genau welche.
SQLSTATE 3D000database does not exist
Oft ist die im Fehler genannte Datenbank Ihr eigener Benutzername — psqls Standard, wenn Sie keinen angeben. Oder Sie sind komplett auf dem falschen Port.
SQLSTATE 28000role does not exist
Frische Installation, und PostgreSQL weiß nicht, wer "ubuntu" ist. Warum der OS-Benutzername auftaucht und wie man Rollen richtig bootstrappt.
SQLSTATE 08006server closed the connection
Entweder ist der Serverprozess gestorben (das Log wird es sagen) oder eine Firewall/NAT hat stillschweigend eine Idle-Verbindung gekappt (das Log wird schweigen). Prüfen Sie zuerst das Log.
Nebenläufigkeit & Sperren
deadlock detected
Zwei Transaktionen halten jeweils einen Lock, den die andere benötigt. Warum das passiert, wie man die DETAIL-Zeilen liest und welche Gewohnheiten bei der Lock-Reihenfolge es verhindern.
SQLSTATE 40001could not serialize access
Repeatable Read oder Serializable weigerte sich, so zu tun, als seien zwei widersprüchliche Transaktionen beide geschehen. Kein Bug — aber Ihr Code muss wiederholen.
SQLSTATE 25P02current transaction is aborted
Nie das eigentliche Problem: eine frühere Anweisung in der Transaktion ist bereits fehlgeschlagen, und PostgreSQL verweigert alles, bis Sie ROLLBACK ausführen.
SQLSTATE 55P03lock timeout
Die Anweisung gab das Warten auf einen Lock auf — weil jemand vernünftigerweise lock_timeout gesetzt hat. Finden Sie den Blockierer und behalten Sie das Fail-Fast-Muster.
SQLSTATE 40001conflict with recovery
Nur auf Replikas: WAL-Replay musste Zeilenversionen entfernen, die Ihre Query noch verwendete. Die Lösung ist ein Kompromiss, den Sie bewusst wählen müssen.
Constraints & Datenintegrität
duplicate key value
Ein Unique-Constraint hat seine Aufgabe erfüllt. Die interessante Frage ist, warum: ein Insert-Race, eine bei einem Import zurückgebliebene Sequenz oder ein wiederholender Client.
SQLSTATE 23502not-null violation
Eine NOT-NULL-Spalte würde leer bleiben. Die heimtückische Variante: Ihr ORM sendet ein explizites NULL, das den DEFAULT der Spalte überschreibt.
SQLSTATE 23503foreign key violation
Zwei Richtungen, ein Constraint: ein Kind, das auf ein fehlendes Elternteil zeigt, oder ein Elternteil, das gelöscht wird, während Kinder es noch referenzieren.
SQLSTATE 22P02invalid input syntax
Ein Textwert konnte nicht als Zieltyp geparst werden. Meist ein Cast auf schmutzige Daten, ein leerer String, wo eine Zahl erwartet wurde, oder eine CSV-Kopfzeile.
SQLSTATE 22001value too long
Daten überschritten ein varchar(n)-Limit und PostgreSQL weigert sich, stillschweigend abzuschneiden. Oft ist die eigentliche Lösung, das (n) selbst zu hinterfragen.
SQLSTATE 22012division by zero
Ein Nenner traf null — meist eine leere Gruppe in einer Aggregation. Der einzeilige Fix, den man sich merken sollte: NULLIF(nenner, 0).
SQLSTATE 42P10no constraint matching ON CONFLICT
ON CONFLICT braucht einen Unique-Index auf genau den Spalten (oder dem Ausdruck oder dem Partial-Prädikat), die Sie genannt haben. Ein normaler Index zählt nicht.
SQL, Typen & Schema
permission denied
Ihrer Rolle fehlt ein Recht — oft weil die Tabellen von der Migrations-Rolle erstellt wurden und niemand der App-Rolle etwas darauf erteilt hat.
SQLSTATE 42P01relation does not exist
Die Tabelle existiert — Sie schauen nur nicht dort, wo PostgreSQL schaut. search_path, gequotete Bezeichner und falsche Datenbank, in dieser Reihenfolge.
SQLSTATE 42703column does not exist
Drei Fallen verursachen die meisten davon: camelCase-Spalten, die Anführungszeichen brauchen, doppelt gequotete "Strings" (das sind Bezeichner!) und Aliase in WHERE.
SQLSTATE 42601syntax error at or near
Das ^ zeigt, wo der Parser aufgab — der Fehler liegt meist dort oder kurz davor. Reservierte Wörter und MySQL-Syntax stehen ganz oben.
SQLSTATE 42883function does not exist
Lesen Sie es als: keine Funktion mit diesem Namen und diesen Argumenttypen. Die Funktion existiert meist — Ihre Argumente haben den falschen Typ.
SQLSTATE 42803must appear in GROUP BY
Sie haben eine Spalte selektiert, die weder gruppiert noch aggregiert ist. Oft ist die eigentliche Absicht "die neueste Zeile pro Gruppe" — was DISTINCT ON will, nicht GROUP BY.
SQLSTATE 21000more than one row returned
Eine skalare Subquery versprach höchstens eine Zeile und lieferte mehrere. Entweder meinten Sie IN — oder Ihre Daten haben Duplikate, die sie nicht haben sollten.
Ressourcen & Betrieb
statement timeout
Eine Query hat statement_timeout überschritten. Finden Sie heraus, ob sie langsam war, an einem Lock blockiert war oder das Timeout irgendwo gesetzt war, wo Sie es vergessen hatten.
SQLSTATE 53200out of shared memory
Trotz des beängstigenden Namens füllt sich fast immer die gemeinsame Lock-Tabelle — typischerweise eine Transaktion, die Tausende Partitionen anfasst.
SQLSTATE 53100no space left on device
Die Platte ist voll — und auf PostgreSQL-Hosts ist der Übeltäter oft WAL, das von einem toten Replikations-Slot zurückgehalten wird. Regel eins: nie von Hand aus dem Datenverzeichnis löschen.
Betriebwraparound protection
Die Notbremse von MVCC: Transaktions-IDs fast erschöpft, weil das Freezing zurückfiel. Finden Sie, was das Vacuum blockierte, und lassen Sie es dann aufholen.
Den SQLSTATE eines Fehlers finden
Jeder PostgreSQL-Fehler trägt einen fünfstelligen SQLSTATE-Code, der stabiler ist als der Meldungstext (und den Ihr Treiber für die programmatische Behandlung bereitstellt). Führen Sie in psql \set VERBOSITY verbose aus, und der Code wird bei jedem Fehler ausgegeben; lesen Sie im Anwendungscode das SQLSTATE-Feld aus dem Fehlerobjekt Ihres Treibers. Die Seiten oben nennen den SQLSTATE, der zu jedem Fehler gehört.
