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
- An error with
XACT_ABORTon. WithSET XACT_ABORT ON, most errors roll back the whole transaction and stop the batch. If your application sendsBEGIN, the statements andCOMMITas separate commands, theCOMMITarrives after the rollback. - A deadlock or a killed session. Being chosen as a deadlock victim (1205) rolls the transaction back.
- A stored procedure that rolled back your transaction. A
ROLLBACKinside a procedure undoes the caller’s transaction too; the caller sees error 266, then 3902 at itsCOMMIT. - Ending it twice. A
CATCHblock rolls back, then code after it rolls back (3903) or commits again; or twoCOMMITs for oneBEGIN. - No
BEGINon this connection. TheBEGIN TRANSACTIONran 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.