Download

The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION

You ran COMMIT (3902) or ROLLBACK (3903) with no transaction open. Usually something already ended it: an error with XACT_ABORT on, a deadlock, a procedure’s ROLLBACK, or an earlier ROLLBACK in your own code, so the work you meant to commit may be gone. Find that first error.

SQL Server error 3902· Tested on SQL Server 2022 RTM-CU27 (16.0.4295.3); same messages on 2019 RTM-CU32-GDR and 2025 RTM-CU9· Updated 11 October 2026

The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

What it means

A COMMIT or ROLLBACK ran while the connection had no open transaction (@@TRANCOUNT was 0):

Msg 3902, Level 16, State 1, Server 7732422b7f56, Line 1
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
Msg 3903, Level 16, State 1, Server 7732422b7f56, Line 1
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.

The error itself changes nothing. What matters is why there was no transaction. Usually your code did start one, and something ended it before the COMMIT: in that case the statements in it were rolled back, and the COMMIT that fails is the first sign. Look for the error that came before this one.

Common causes

  1. An error with XACT_ABORT on. With SET XACT_ABORT ON, most errors roll back the whole transaction and stop the batch. If your application sends BEGIN, the statements and COMMIT as separate commands, the COMMIT arrives after the rollback.
  2. A deadlock or a killed session. Being chosen as a deadlock victim (1205) rolls the transaction back.
  3. A stored procedure that rolled back your transaction. A ROLLBACK inside a procedure undoes the caller’s transaction too; the caller sees error 266, then 3902 at its COMMIT.
  4. Ending it twice. A CATCH block rolls back, then code after it rolls back (3903) or commits again; or two COMMITs for one BEGIN.
  5. No BEGIN on this connection. The BEGIN TRANSACTION ran on a different connection, such as another one from the application’s pool, or in a script that never ran it.

A ROLLBACK TRANSACTION <name> with a name that isn’t an open transaction or savepoint is a different error, 6401 (Cannot roll back <name>. No transaction or savepoint of that name was found.).

How to fix it

Find what ended the transaction

Read the errors before this one: a 547, 2627, 1205 or 3930 right before the COMMIT is the real problem, and its statements need running again once it’s fixed. Check whether the data you expected is there.

Only end a transaction that’s open

In T-SQL, check before you commit or roll back, and in CATCH use XACT_STATE():

BEGIN TRY
  BEGIN TRANSACTION;
  INSERT INTO dbo.orders (customer_id, total) VALUES (@customer_id, @total);
  UPDATE dbo.customers SET order_count += 1 WHERE id = @customer_id;
  COMMIT;
END TRY
BEGIN CATCH
  IF XACT_STATE() <> 0 ROLLBACK;
  THROW;
END CATCH;

THROW re-raises the original error, so the caller sees what went wrong rather than a 3903 from a second rollback. IF @@TRANCOUNT > 0 COMMIT; is the plain guard where there’s no CATCH.

Use the driver’s transaction, on one connection

In application code, open the transaction with the driver (for example BeginTransaction() in .NET, or your ORM’s transaction scope) and run every command on that same connection, rather than sending BEGIN TRANSACTION and COMMIT as text. Then a rollback by the server shows up as an exception at the statement that failed, not as a puzzling 3902 later.

Don’t roll back the caller’s transaction

Procedures that may be called inside a transaction should roll back to a savepoint, not the whole transaction; error 266’s page has the pattern.

Reproduce it

On SQL Server 2022 (16.0.4295.3) with sqlcmd: COMMIT; and ROLLBACK; on their own gave the two messages shown above. With XACT_ABORT on, a transaction whose insert broke a foreign key, followed by the COMMIT in a separate batch, as an application would send it:

SET XACT_ABORT ON;
BEGIN TRANSACTION;
INSERT INTO seo_err_mssql.orders (customer_id, total) VALUES (999, 1);
-- next batch
COMMIT;
Msg 547, Level 16, State 1, Server 7732422b7f56, Line 3
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_orders_customers". The conflict occurred in database "inlet", table "seo_err_mssql.customers", column 'id'.
Msg 3902, Level 16, State 1, Server 7732422b7f56, Line 1
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

A TRY … CATCH whose CATCH rolled back, followed by another ROLLBACK after it, gave Msg 3903, Level 16, State 1, … Line 11. BEGIN TRANSACTION, an update, then COMMIT twice gave 3902 at the second. A procedure ending in ROLLBACK, called inside a transaction, gave 266 and then 3902 at the caller’s COMMIT. ROLLBACK TRANSACTION no_such_savepoint inside a transaction gave 6401. With IF @@TRANCOUNT > 0 COMMIT; written twice after one BEGIN, there was no error and @@TRANCOUNT ended at 0. SQL Server 2019 and 2025 printed the same messages.

In Inlet

Query tabs offer transactions with manual commit, so you decide when to commit or roll back. When SQL Server refuses a COMMIT, Inlet shows its message with SQL Server error 3902, state 1, severity 16 and links to this page. Grid edits are staged and committed together (⌘S), in one transaction.

Inlet: a database client for the Mac

One native app for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and Redis. It explains errors where they happen, holds your edits until you save them, and keeps production read-only until you say so.

Version 0.1.0 · macOS 26 Tahoe or later · Apple silicon and Intel