Error de PostgreSQL: current transaction is aborted
ERROR: current transaction is aborted, commands ignored until end of transaction block
Este error nunca es la causa raíz. Alguna sentencia anterior de la misma transacción ya falló, la transacción entró en estado abortado, y PostgreSQL ahora rechaza cada comando posterior hasta que termines la transacción con ROLLBACK. La pregunta a responder es siempre: ¿cuál fue el primer error?
Qué significa este error
Una vez que cualquier sentencia dentro de una transacción falla, PostgreSQL garantiza que la transacción en su conjunto no puede hacer commit — permitir que más sentencias "tuvieran éxito" te dejaría hacer commit de una unidad de trabajo aplicada a medias. Así que las rechaza todas, repitiendo este mensaje, hasta que la aplicación emite ROLLBACK (o revierte a un savepoint tomado antes del fallo).
Si ves oleadas de 25P02 en tus logs, léelas como un síntoma con dos capas: un error original (una línea, fácil de pasar por alto) y una aplicación que siguió usando la conexión como si nada hubiera pasado (la oleada).
Causas comunes
- La aplicación se traga la primera excepción — un try/catch que registra y continúa, todavía dentro de la transacción, todavía en la misma conexión.
- Código de framework o driver que no hace rollback ante un error antes de reutilizar la sesión.
- Un pool de conexiones entregando una conexión atascada en una transacción fallida porque no resetea el estado al liberarla.
- Scripts de psql ejecutándose dentro de
BEGIN ... COMMITque continúan tras un error (por defecto psql sigue adelante).
Cómo diagnosticarlo
- En el log del servidor, mira qué hizo la misma sesión justo antes de la oleada de 25P02 — con
%p(pid) enlog_line_prefixpuedes seguir la sesión; el primerERRORde ese pid es tu problema real. - En la aplicación, registra e inspecciona la primera excepción, no las posteriores: un emparejamiento muy común es una violación de clave duplicada seguida de un torrente de 25P02 de código que la "manejó" y siguió adelante.
- Interactivamente en psql el error original es simplemente el que se imprime justo encima.
Cómo solucionarlo
- Ante cualquier error de sentencia, haz rollback — luego reintenta la transacción completa si procede. Estructura el código de modo que una excepción dentro de una transacción no pueda capturarse sin terminar la transacción.
- Fallos esperados → savepoints, para que un fallo no envenene la transacción:
Mejor aún, cuando el fallo esperado es un duplicado, usaBEGIN; SAVEPOINT attempt; INSERT INTO users ...; -- puede fallar -- en caso de error: ROLLBACK TO SAVEPOINT attempt; -- la transacción sigue siendo utilizable COMMIT;ON CONFLICTy evita el error por completo. - Scripts: ejecuta psql con
ON_ERROR_STOP(psql -v ON_ERROR_STOP=1) para que un error detenga el script en vez de encadenar; interactivamente,\set ON_ERROR_ROLLBACK interactivehace que psql envuelva las sentencias en savepoints por ti. - Pools: asegúrate de que las conexiones se revierten / resetean (p. ej.
DISCARD ALL) al devolverlas al pool.
