From f3785f10a283890c10c4bc76fe201ed5a98fa99a Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Mon, 29 Jun 2026 22:48:25 +0530 Subject: [PATCH] fix(accounts): savepoint per-row merge in Ledger Merge (Postgres) start_merge merges accounts in a loop; on failure it only rolled back when not in_test, so in tests a failed merge_account left the Postgres txn poisoned and the except log_error + the finally db_set(status) raised InFailedSqlTransaction. Wrap each row in savepoint('ledger_merge_row') and rollback to it unconditionally before log_error - this recovers the txn in both paths without the full rollback discarding the rest of the test transaction. Production still commits per successful merge, so the per-iteration savepoint rollback is equivalent to the prior full rollback. No-op on MariaDB. --- erpnext/accounts/doctype/ledger_merge/ledger_merge.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/ledger_merge/ledger_merge.py b/erpnext/accounts/doctype/ledger_merge/ledger_merge.py index a219e21526d..cd574eafaa3 100644 --- a/erpnext/accounts/doctype/ledger_merge/ledger_merge.py +++ b/erpnext/accounts/doctype/ledger_merge/ledger_merge.py @@ -65,6 +65,7 @@ def start_merge(docname): total = len(ledger_merge.merge_accounts) for row in ledger_merge.merge_accounts: if not row.merged: + frappe.db.savepoint("ledger_merge_row") try: merge_account( row.account, @@ -79,8 +80,7 @@ def start_merge(docname): {"ledger_merge": ledger_merge.name, "current": successful_merges, "total": total}, ) except Exception: - if not frappe.in_test: - frappe.db.rollback() + frappe.db.rollback(save_point="ledger_merge_row") ledger_merge.log_error("Ledger merge failed") finally: if successful_merges == total: