From c58a4026a74855b134913b01846813128490eaba Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Wed, 1 Jul 2026 11:55:41 +0530 Subject: [PATCH] fix(integrations): per-transaction savepoint in Plaid sync_transactions new_bank_transaction inserts+submits Bank Transactions in a loop within one transaction. On a failed insert/submit, Postgres poisons the transaction so the except's log_error dies with InFailedSqlTransaction; MariaDB keeps the Bank Transactions synced before the failure. A full rollback would discard those on MariaDB too, so wrap each iteration in a savepoint + rollback(save_point=) and re-raise -- preserves MariaDB's partial-sync behaviour and heals the Postgres txn. The sibling handlers add_institution / add_bank_accounts were already fixed; this closes the third. Co-Authored-By: Claude Opus 4.8 --- .../doctype/plaid_settings/plaid_settings.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py index 25d5a861a4b..bcab065bba4 100644 --- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py +++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py @@ -215,7 +215,14 @@ def sync_transactions(bank, bank_account): result = [] if transactions: for transaction in reversed(transactions): - result += new_bank_transaction(transaction) + # per-transaction savepoint: a failed insert/submit must not discard the Bank + # Transactions already synced this run (MariaDB keeps them) nor poison the txn on Postgres + frappe.db.savepoint("plaid_sync_txn") + try: + result += new_bank_transaction(transaction) + except Exception: + frappe.db.rollback(save_point="plaid_sync_txn") + raise if result: last_transaction_date = frappe.db.get_value("Bank Transaction", result.pop(), "date")