Referencia de errores de PostgreSQL
Los errores que PostgreSQL te lanza de verdad en producción, una página para cada uno: qué significa el mensaje, las causas típicas, cómo diagnosticarlo y cómo solucionarlo — con comandos reales, sin rodeos.
Conexiones y autenticación
too many clients
max_connections está agotado. Cómo ver quién sostiene los slots, y por qué la solución real suele ser un pooler de conexiones, no un límite mayor.
Conexionesconnection refused
La conexión TCP nunca llegó a PostgreSQL en absoluto. Servidor caído, puerto incorrecto, listen_addresses, firewall o red de Docker — en ese orden.
SQLSTATE 28P01password authentication failed
A veces la contraseña realmente es incorrecta. Las otras veces: el rol no tiene contraseña, un desajuste SCRAM/md5, o un URI que necesitaba percent-encoding.
SQLSTATE 28000no pg_hba.conf entry
El servidor es alcanzable pero ninguna regla de pg_hba.conf coincide con tu combinación de (host, base de datos, usuario, SSL). El error te dice exactamente cuál.
SQLSTATE 3D000database does not exist
A menudo la base de datos nombrada en el error es tu propio nombre de usuario — el valor por defecto de psql cuando no especificas uno. O estás en el puerto equivocado por completo.
SQLSTATE 28000role does not exist
Instalación nueva, y PostgreSQL no sabe quién es "ubuntu". Por qué aparece el nombre de usuario del SO, y cómo hacer el bootstrap de roles correctamente.
SQLSTATE 08006server closed the connection
O el proceso del servidor murió (el log lo dirá) o un firewall/NAT cortó silenciosamente una conexión inactiva (el log estará en silencio). Comprueba el log primero.
Concurrencia y bloqueos
deadlock detected
Dos transacciones sostienen cada una un bloqueo que la otra necesita. Por qué ocurre, cómo leer las líneas DETAIL, y los hábitos de ordenación de bloqueos que lo previenen.
SQLSTATE 40001could not serialize access
Repeatable Read o Serializable se negó a fingir que dos transacciones en conflicto ocurrieron ambas. No es un bug — pero tu código debe reintentar.
SQLSTATE 25P02current transaction is aborted
Nunca es el problema real: una sentencia anterior de la transacción ya falló, y PostgreSQL está rechazando todo hasta que hagas ROLLBACK.
SQLSTATE 55P03lock timeout
La sentencia se rindió esperando un bloqueo — porque alguien configuró sensatamente lock_timeout. Encuentra al bloqueador, y conserva el patrón de fallar rápido.
SQLSTATE 40001conflict with recovery
Solo en réplicas: el replay de WAL necesitaba eliminar versiones de fila que tu consulta aún estaba usando. La solución es un compromiso que debes elegir conscientemente.
Restricciones e integridad de datos
duplicate key value
Una restricción unique hizo su trabajo. La pregunta interesante es por qué: una carrera de inserción, una secuencia dejada atrás por una importación, o un cliente reintentando.
SQLSTATE 23502not-null violation
Una columna NOT NULL acabaría vacía. La variante traicionera: tu ORM envía un NULL explícito, que anula el DEFAULT de la columna.
SQLSTATE 23503foreign key violation
Dos direcciones, una restricción: un hijo apuntando a un padre inexistente, o un padre que se borra mientras los hijos aún lo referencian.
SQLSTATE 22P02invalid input syntax
Un valor de texto no pudo parsearse como el tipo de destino. Normalmente un cast sobre datos sucios, una cadena vacía donde se esperaba un número, o una cabecera de CSV.
SQLSTATE 22001value too long
Los datos superaron un límite varchar(n) y PostgreSQL se niega a truncar en silencio. A menudo la solución real es cuestionar el propio (n).
SQLSTATE 22012division by zero
Un denominador llegó a cero — normalmente un grupo vacío en una agregación. La solución de una línea que vale la pena memorizar: NULLIF(denominator, 0).
SQLSTATE 42P10no constraint matching ON CONFLICT
ON CONFLICT necesita un índice único sobre exactamente las columnas (o expresión, o predicado parcial) que nombraste. Un índice normal no cuenta.
SQL, tipos y esquema
permission denied
Tu rol carece de un privilegio — a menudo porque las tablas fueron creadas por el rol de migración y nadie concedió nada al rol de la aplicación sobre ellas.
SQLSTATE 42P01relation does not exist
La tabla existe — solo que no estás mirando donde PostgreSQL mira. search_path, identificadores entrecomillados y base de datos incorrecta, en ese orden.
SQLSTATE 42703column does not exist
Tres trampas causan la mayoría: columnas camelCase que necesitan comillas, "cadenas" con comillas dobles (¡eso son identificadores!), y alias en WHERE.
SQLSTATE 42601syntax error at or near
El cursor apunta a donde el parser se rindió — el error suele estar en él o justo antes. Las palabras reservadas y la sintaxis de MySQL encabezan la lista.
SQLSTATE 42883function does not exist
Léelo como: ninguna función con ese nombre y esos tipos de argumento. La función normalmente existe — tus argumentos son del tipo incorrecto.
SQLSTATE 42803must appear in GROUP BY
Seleccionaste una columna que ni se agrupa ni se agrega. A menudo la intención real es "la última fila por grupo" — que quiere DISTINCT ON, no GROUP BY.
SQLSTATE 21000more than one row returned
Una subconsulta escalar prometió como mucho una fila y entregó varias. O querías decir IN — o tus datos tienen duplicados que no deberían existir.
Recursos y operaciones
statement timeout
Una consulta superó statement_timeout. Averigua si fue lenta, bloqueada en un lock, o si el timeout estaba configurado en un sitio que olvidaste.
SQLSTATE 53200out of shared memory
A pesar del nombre alarmante, casi siempre es la tabla de bloqueos compartida llenándose — típicamente una transacción tocando miles de particiones.
SQLSTATE 53100no space left on device
El disco está lleno — y en hosts de PostgreSQL el culpable a menudo es WAL retenido por un slot de replicación muerto. Regla uno: nunca borres a mano del directorio de datos.
Operacioneswraparound protection
El freno de emergencia de MVCC: los IDs de transacción casi agotados porque el freezing se quedó atrás. Encuentra qué bloqueó el vacuum, y luego déjalo ponerse al día.
Encontrar el SQLSTATE de un error
Cada error de PostgreSQL lleva un código SQLSTATE de cinco caracteres, más estable que el texto del mensaje (y es lo que tu driver expone para el manejo programático). En psql, ejecuta \set VERBOSITY verbose y el código se imprime con cada error; en el código de la aplicación, lee el campo SQLSTATE del objeto de error de tu driver. Las páginas anteriores indican el SQLSTATE que corresponde a cada error.
