Ask me anything
Ithy Logo
Sign in to save

SQL Server error 3930: XACT_STATE and the original error

SQL Server error 3930 means an operation tried to write or commit while the transaction was uncommittable. Find the earlier error that caused that state, capture its details and roll back the failed transaction. The message's reference to the transaction log is not, by itself, a diagnosis that the log file is full or corrupt.

Interpret the transaction state

SQL Server XACT_STATE values
ValueMeaningConsequence
0No active user transaction in the current session.There is no such transaction to commit.
1An active transaction is committable.The application must still decide whether committing is correct for its operation.
-1An active transaction is uncommittable.It cannot commit, perform writes or roll back to a savepoint; a full rollback is required.

Microsoft's XACT_STATE reference also distinguishes this function from @@TRANCOUNT: a positive transaction count does not prove that the transaction is committable.

Capture the first error before creating another one

Inspect the client messages and relevant application diagnostics before 3930. In a CATCH block, capture ERROR_NUMBER(), ERROR_MESSAGE(), ERROR_PROCEDURE() and ERROR_LINE(). If the transaction is uncommittable, attempting to insert a diagnostic row inside it can itself cause 3930 and obscure the original failure.

The following pattern assumes this block owns its top-level transaction. It is not a drop-in transaction manager for a procedure called inside someone else's transaction.

SET XACT_ABORT ON;
BEGIN TRY
    BEGIN TRANSACTION;
    -- The application operation belongs here.
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    SELECT ERROR_NUMBER() AS error_number,
           ERROR_MESSAGE() AS error_message,
           ERROR_PROCEDURE() AS error_procedure,
           ERROR_LINE() AS error_line,
           XACT_STATE() AS transaction_state;
    IF XACT_STATE() <> 0
        ROLLBACK TRANSACTION;
    THROW;
END CATCH;

The final THROW preserves the original failure for the caller. SET XACT_ABORT affects runtime error handling and has important interactions with TRY...CATCH; it does not make every possible error identical. Existing applications should test the relevant behavior before changing this setting.

A disposable constraint-error demonstration

Use a fresh test session with no existing transaction. This example creates only a session-local temporary table. It deliberately violates a positive-value constraint so the original error and transaction state can be observed. Do not adapt it by experimenting on production tables.

IF @@TRANCOUNT <> 0
    THROW 50001, 'Use a fresh test session with no active transaction.', 1;
SET XACT_ABORT ON;
CREATE TABLE #TransactionExample (amount int NOT NULL CHECK (amount > 0));
BEGIN TRY
    BEGIN TRANSACTION;
    INSERT INTO #TransactionExample (amount) VALUES (-1);
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    SELECT ERROR_NUMBER() AS original_error,
           XACT_STATE() AS state_before_rollback;
    IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
    THROW;
END CATCH;

Microsoft documents constraint errors with XACT_ABORT ON inside TRY...CATCH as an example of an uncommittable transaction. This published demonstration was reviewed against that documentation, not executed against a SQL Server instance here. It is not a diagnosis of a reader's own failure.

A deadlock victim is a different case

The earlier answer incorrectly implied that a deadlock victim necessarily remains in the same uncommittable state. Microsoft's deadlocks guide states that SQL Server rolls back the chosen victim's transaction and returns error 1205. Inspect the actual error and state. Any retry must account for the whole application operation and its side effects; blindly retrying every 3930 or only the final statement is not a general repair.

Repair the cause, not just the final symptom

Investigate the observed constraint, conversion, trigger or other preceding failure. A separate log-full error requires its own evidence and remedy; do not shrink a database log merely because 3930 mentions writing to it. Capture a reproducible failure, preserve the original error and test the corrected transaction boundaries in an appropriate environment. The TRY...CATCH reference explains additional scope and handling limits.

AI-assisted research. Sources, methodology and corrections · Source-checked guides and tools · Explore published answers

Ask Ithy AI