How to fix 3B000: savepoint_exception in PostgreSQL
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;- Verify the savepoint is within an active transaction
- Check PostgreSQL logs for context
- Review ORM transaction handling
- Verify transaction isolation and error handling
BEGIN;SAVEPOINT my_savepoint;-- Your operations hereROLLBACK 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
- 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
- Savepoint name conflicts when multiple savepoints with identical names exist in the same transaction
- Database connection reset or reuse between savepoint creation and rollback operations
- Transaction being aborted by a previous error, causing subsequent savepoint operations to fail
How to fix "3B000: savepoint_exception"
Check your application code to ensure savepoints are only created and used within transaction blocks. Savepoints cannot be used outside transactions.
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.
Review your PostgreSQL server logs to understand what operation preceded the error. Enable logging if not already enabled:
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).
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.
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:
BEGIN;
-- Operation that fails
-- Transaction is now aborted
ROLLBACK TO SAVEPOINT sp1; -- This will also fail
ROLLBACK; -- Reset to clean stateWrap database operations in proper exception handlers to prevent transaction corruption.
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.
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
- 📚PostgreSQL Official Documentation
- 📖postgresql.org - sql savepoint(Official Docs)
- 📖pganalyze.com - U134(Official Docs)
- 🐙github.com - 134(GitHub)
- 🐙github.com - 8(GitHub)
- 🔗