sqlalchemy.exc.PendingRollbackError: This Session's transaction has been rolled back due to a previous exception during flush.
Python · updated 2026-11-03
Raised by the next operation on a Session after a flush or commit failed and nobody called rollback(). It is a follow-on error: the real cause (an IntegrityError, a dropped connection) happened earlier, often in a different request handled by the same session.
sqlalchemy.exc.PendingRollbackError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was: (psycopg.errors.UniqueViolation) duplicate key value violates unique constraint "users_email_key"
Quick fix
Read the 'Original exception was' part: that is the real error to fix. Then make sure every place that catches a database error calls session.rollback(), and that sessions are scoped to one request or job instead of shared.
- Copy the 'Original exception was:' text: it names the first failure (often IntegrityError or OperationalError).
- Fix that first error, or handle it: catch it, call session.rollback(), then continue or return an error.
- Use a session per request (FastAPI dependency with yield, Flask-SQLAlchemy scoped session) so one failure does not poison later requests.
- Prefer with Session(engine) as session, session.begin(): blocks, which roll back automatically on errors.
- For dropped connections, set pool_pre_ping=True on the engine.
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session
def create_user(session: Session, email: str):
try:
session.add(User(email=email))
session.commit()
except IntegrityError:
session.rollback() # without this, every later query raises PendingRollbackError
raise EmailTaken(email)
# Or let a context manager handle it
with Session(engine) as session, session.begin():
session.add(User(email=email)) # commits on success, rolls back on any exceptionWhy it happens
An exception caught without rollback
A try/except around commit() that logs the IntegrityError and moves on leaves the session in a failed state; the next query raises this error.
One session shared across requests
A module-level session or a session stored on the app object means one failed request breaks every request after it until the process restarts.
A dropped database connection
A connection killed by the server or a proxy mid-transaction fails the flush; without pre-ping and rollback, the session stays unusable.
Background tasks reusing the request session
A background job that receives the request's session can run after the request failed and inherit its broken transaction.
Other fixes
- Log the original exception where it happens; PendingRollbackError on its own hides the real cause.
- In Flask-SQLAlchemy, call db.session.rollback() in an error handler for database exceptions.
Same error, other wording
- sqlalchemy.exc.PendingRollbackError: Can't reconnect until invalid transaction is rolled back.
- sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush.
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the PendingRollbackError exceptions in production, extract the original exception from each message, show me where the first error is caught without session.rollback(), and fix the session handling.
Related errors
- psycopg.errors.UniqueViolation: duplicate key value violates unique constraint...
- psycopg2.OperationalError: server closed the connection unexpectedly
- django.db.utils.OperationalError: no such table: orders_order
References: SQLAlchemy docs: error messages (PendingRollbackError), SQLAlchemy docs: session basics (begin, commit, rollback)