How to fix 3B000: savepoint_exception in PostgreSQL

PostgreSQLINTERMEDIATEHIGHUpdated Dec 22, 2025· 109 views

PostgreSQL error 3B000 indicates a general savepoint exception, typically occurring when attempting to rollback or release a savepoint that no longer exists. This commonly happens in ORMs when transaction state becomes desynchronized.

Quick fix

Fixes 3B000: savepoint_exception

BEGIN;
  SAVEPOINT my_savepoint;
  -- Your operations here
  ROLLBACK TO SAVEPOINT my_savepoint;
COMMIT;
  1. Verify the savepoint is within an active transaction
  2. Check PostgreSQL logs for context
  3. Review ORM transaction handling
  4. Verify transaction isolation and error handling
postgresql — error
BEGIN;
SAVEPOINT my_savepoint;
-- Your operations here
ROLLBACK TO SAVEPOINT my_savepoint;
COMMIT;
3B000: savepoint_exception

What this error means

Error code 3B000 belongs to PostgreSQL's "Class 3B — Savepoint Exception" category and represents a general savepoint-related error. A savepoint is a named marker within a transaction that allows you to roll back all commands executed after it was established, without rolling back the entire transaction. This error occurs when your application attempts to manipulate a savepoint that no longer exists, usually because the parent transaction has already been committed or rolled back. The error is especially common in ORM frameworks (like Django, Doctrine, Ecto) that use savepoints to implement nested transactions.

Typical symptoms

  • Application throws "savepoint_exception" when performing database operations
  • ORM frameworks fail during rollback operations with "no such savepoint" message
  • Nested transaction operations in your application suddenly fail
  • Error appears intermittently in high-concurrency scenarios
  • Stack trace shows ORM transaction management code before the error

Common causes

  1. ORM framework bug causing desynchronization between expected and actual savepoints
  2. Application attempting to rollback a savepoint after the parent transaction has already been committed
  3. Multiple threads or async operations accessing the same transaction without proper synchronization
  4. Savepoint name conflicts when multiple savepoints with identical names exist in the same transaction
  5. Database connection reset or reuse between savepoint creation and rollback operations
  6. Transaction being aborted by a previous error, causing subsequent savepoint operations to fail

How to fix "3B000: savepoint_exception"

1Verify the savepoint is within an active transaction

Check your application code to ensure savepoints are only created and used within transaction blocks. Savepoints cannot be used outside transactions.

sql
BEGIN;
  SAVEPOINT my_savepoint;
  -- Your operations here
  ROLLBACK TO SAVEPOINT my_savepoint;
COMMIT;

If using an ORM, verify that nested transactions are being created within an active parent transaction.

2Check PostgreSQL logs for context

Review your PostgreSQL server logs to understand what operation preceded the error. Enable logging if not already enabled:

sql
ALTER SYSTEM SET log_statement = 'all';
SELECT pg_reload_conf();

Then check the log file (usually in /var/log/postgresql/ on Linux or the configured log directory).

3Review ORM transaction handling

If using an ORM (Django, Doctrine, SQLAlchemy, Ecto, etc.), verify the ORM's savepoint/nested transaction implementation:

Django: Ensure you're using transaction.atomic() correctly and not mixing manual savepoints with ORM nested transactions.

Doctrine/Symfony: Update to the latest version as savepoint bugs have been fixed in newer releases.

Ecto: Check that you're not attempting to rollback savepoints outside the transaction context.

Consider adding debugging logs to trace exactly which savepoint is being referenced when the error occurs.

4Verify transaction isolation and error handling

Ensure errors are properly caught and don't leave the transaction in an aborted state. In PostgreSQL, once an error occurs in a transaction, the entire transaction becomes aborted:

sql
BEGIN;
  -- Operation that fails
  -- Transaction is now aborted
  ROLLBACK TO SAVEPOINT sp1;  -- This will also fail
ROLLBACK;  -- Reset to clean state

Wrap database operations in proper exception handlers to prevent transaction corruption.

5Update or patch your ORM

If the issue is with your ORM, check the issue tracker for known savepoint/nested transaction bugs:

- Django: https://code.djangoproject.com/ - search for savepoint issues
- Doctrine: Check GitHub issues in dmaicher/doctrine-test-bundle
- Ecto: https://github.com/elixir-ecto/ecto_sql
- Npgsql (.NET): https://github.com/npgsql/npgsql

Upgrade to the latest stable version where the bug may already be fixed.

6Disable nested transaction/savepoint mode if unnecessary

If your application doesn't require nested transactions, consider disabling savepoint mode in your ORM configuration:

Django: Set "ATOMIC_REQUESTS": False if you don't need automatic transaction wrapping.

Doctrine: Use standard transactions instead of nested transactions if the use case doesn't require them.

This eliminates the complexity and potential for savepoint-related errors.

Advanced notes

Savepoints can only be used within transaction blocks (BEGIN/COMMIT). In PL/pgSQL stored procedures, you cannot use explicit SAVEPOINT/ROLLBACK commands. Instead, PL/pgSQL automatically creates implicit savepoints for EXCEPTION blocks. If you have more than PGPROC_MAX_CACHED_SUBXIDS (64 by default) active subtransactions in a session, performance degradation may occur. Monitor savepoint usage in high-concurrency applications to prevent this. The error class 3B includes both 3B000 (general savepoint exception) and 3B001 (invalid_savepoint_specification) - both have similar root causes related to savepoint lifecycle management.

Frequently asked questions

What does "3B000: savepoint_exception" mean?
Error code 3B000 belongs to PostgreSQL's "Class 3B — Savepoint Exception" category and represents a general savepoint-related error. A savepoint is a named marker within a transaction that allows you to roll back all commands executed after it was established, without rolling back the entire transaction. This error occurs when your application attempts to manipulate a savepoint that no longer exists, usually because the parent transaction has already been committed or rolled back.
How do I fix "3B000: savepoint_exception"?
PostgreSQL error 3B000 indicates a general savepoint exception, typically occurring when attempting to rollback or release a savepoint that no longer exists. This commonly happens in ORMs when transaction state becomes desynchronized.
What causes "3B000: savepoint_exception"?
ORM framework bug causing desynchronization between expected and actual savepoints Application attempting to rollback a savepoint after the parent transaction has already been committed Multiple threads or async operations accessing the same transaction without proper synchronization
Is the "3B000: savepoint_exception" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading