Troubleshooting Guide: SQL Server Error 3978
Beginning a new transaction after rollback to save point is not allowed
Why This Error Happens
This error occurs when an application attempts to initiate a new transaction immediately after rolling back to a savepoint within the same batch, without properly committing or fully rolling back the parent transaction first. SQL Server 2025 enforces strict transaction state validation, and a rollback to a savepoint only reverts data changes — it does not close out the outer transaction context, leaving the connection in an ambiguous state. This is commonly triggered by poorly structured transaction logic in stored procedures, ORMs (like Entity Framework or Dapper), or application connection pooling where a prior transaction wasn’t fully disposed before a new one was opened on the same connection.
Step-by-Step Resolution Guide
Step 1: Review the Transaction Logic in the Source Code
- Locate the stored procedure or application code throwing Error 3978 using SQL Server Profiler or Extended Events (
xEvents) filtered onerror_reportedwith error number3978. - Check for a pattern like
SAVE TRANSACTION, followed byROLLBACK TRANSACTION SavepointName, and then immediatelyBEGIN TRANSACTIONwithout an interveningCOMMITor fullROLLBACK. - Ensure every
BEGIN TRANSACTIONhas a matchingCOMMIT TRANSACTIONor a fullROLLBACK TRANSACTION(without a savepoint name) before starting a new one.
Step 2: Correct the Transaction Control Flow in T-SQL
- Modify the procedure logic so that after
ROLLBACK TRANSACTION SavepointName, you either continue work inside the same outer transaction or issue a fullROLLBACK TRANSACTION(no savepoint name) to close it out completely. - Example corrected pattern:
BEGIN TRANSACTION;
SAVE TRANSACTION MySavePoint;
-- logic here
ROLLBACK TRANSACTION MySavePoint;
-- continue or commit the SAME transaction, do not start a new one here
COMMIT TRANSACTION;
- Avoid nesting a
BEGIN TRANSACTIONcall directly after a savepoint rollback within the same@@TRANCOUNTscope.
Step 3: Audit Application-Level Connection and ORM Settings
- On Windows Server 2025/Windows 11 hosts, check the application’s connection string for
Enlist=trueor pooling settings that may reuse a connection with a lingering transaction state. - For .NET apps, verify
TransactionScopeobjects are disposed properly usingusingblocks and that nested scopes useTransactionScopeOption.Requiredcorrectly. - Restart the application pool (IIS) or the service host to clear any connections stuck in a bad transaction state:
Restart-WebAppPool -Name "YourAppPoolName"
Step 4: Validate SQL Server Configuration and Patch Level
- Confirm SQL Server 2025 is on the latest Cumulative Update via SQL Server Configuration Manager or
SELECT @@VERSION;. - Check
sys.dm_tran_active_transactionsandsys.dm_tran_session_transactionsDMVs to identify sessions stuck with uncommitted nested transactions. - If a session is orphaned, isolate and kill it using
KILL <session_id>;after confirming it is safe to terminate.
Alternative or Verification Steps
- Re-run the transaction/procedure in SQL Server Management Studio (SSMS) manually, checking
@@TRANCOUNTbefore and after eachCOMMIT/ROLLBACKto confirm it returns to0cleanly. - If the error persists, wrap the entire logic in a
TRY...CATCHblock withXACT_STATE()checks to programmatically detect and fully roll back doomed transactions before allowing any newBEGIN TRANSACTIONcall.