How to fix Error 3990 on Windows Server 2025 / Windows 11

Troubleshooting Guide: Error 3990 – “Transaction Is Not Allowed to Commit Inside of a User Defined Routine”

Why This Error Happens

This error occurs because SQL Server 2025 does not permit a stored procedure, trigger, or user-defined function to commit or roll back a transaction that it did not explicitly begin itself. Typically, this happens when a nested stored procedure calls COMMIT TRANSACTION or ROLLBACK TRANSACTION without matching the exact transaction count (@@TRANCOUNT) at the scope in which it was opened. It can also surface when a trigger attempts to manage transaction state directly, which violates SQL Server’s strict transaction nesting rules.

Step-by-Step Resolution Guide

Step 1: Audit the Transaction Nesting in Your Code

  • Open the stored procedure or routine referenced in the error log and locate every BEGIN TRAN, COMMIT, and ROLLBACK statement.
  • Check the value of @@TRANCOUNT before and after each block to ensure the routine isn’t closing a transaction it did not open.
  • Run the following diagnostic query to capture the current transaction state during execution:
  SELECT @@TRANCOUNT AS CurrentTranCount;

Step 2: Refactor the Routine to Use SAVEPOINTS Instead of Direct Commits

  • Replace internal COMMIT TRANSACTION calls within nested procedures with SAVE TRANSACTION (savepoints) so only the outermost caller controls the final commit.
  • Update the routine logic as follows:
  BEGIN TRY
      SAVE TRANSACTION MySavePoint;
      -- business logic here
  END TRY
  BEGIN CATCH
      ROLLBACK TRANSACTION MySavePoint;
  END CATCH
  • Ensure the outermost calling script (not the inner procedure) is solely responsible for the final COMMIT.

Step 3: Validate Trigger Logic (If Applicable)

  • If the error originates from an INSTEAD OF or AFTER trigger, remove any explicit COMMIT or ROLLBACK statements inside the trigger body.
  • Triggers should rely on RAISERROR or THROW to signal failure, allowing the calling transaction scope to decide whether to roll back.
  • Re-deploy the modified trigger using SQL Server Management Studio (SSMS) 21 or Azure Data Studio connected to your Windows Server 2025 instance.

Step 4: Check XACT_ABORT and Transaction Isolation Settings

  • Verify that SET XACT_ABORT ON; is declared at the top of the routine to ensure automatic rollback on runtime errors, preventing orphaned transaction states.
  • Confirm the connection string used by the application (especially if running on Windows 11 client machines) isn’t manually overriding transaction isolation levels mid-session.

Alternative or Verification Steps

  • To verify the fix, execute the stored procedure manually in SSMS while monitoring SELECT @@TRANCOUNT; before and after execution—it should return to 0 after the outer transaction commits successfully.
  • If the error persists, use SQL Server Profiler or Extended Events to trace the exact nesting level where the COMMIT is being rejected, as this often reveals a secondary hidden procedure call causing the conflict.