From 35a9d7b09c4e979192fefd6f0b17713ee5dfda9f Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 16 Jul 2026 09:21:17 +0530 Subject: [PATCH] fix(accounts): block GL Entry inserts during account rename on postgres The for_update read in _ensure_idle_system only blocks new GL inserts on MariaDB, via the gap lock it takes; a postgres row lock never blocks inserts, so the guard silently degraded to the 5-minute recency check. LOCK TABLE IN EXCLUSIVE MODE blocks writers (not readers) until the rename commits and NOWAIT keeps the wait=False fail-fast, feeding the existing QueryTimeoutError path. --- erpnext/accounts/doctype/account/account.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index ebfb2d0bcee..e67b29bc1be 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -659,8 +659,15 @@ def _ensure_idle_system(): last_gl_update = None try: - # We also lock inserts to GL entry table with for_update here. - last_gl_update = frappe.db.get_value("GL Entry", {}, "modified", for_update=True, wait=False) + if frappe.db.db_type == "postgres": + # The MariaDB branch blocks new GL inserts via the gap lock its for_update read takes; + # a postgres row lock never blocks inserts, so take an EXCLUSIVE table lock instead -- + # writers block until the rename commits, readers don't. NOWAIT mirrors wait=False. + frappe.db.sql("LOCK TABLE `tabGL Entry` IN EXCLUSIVE MODE NOWAIT") + last_gl_update = frappe.db.get_value("GL Entry", {}, "modified") + else: + # We also lock inserts to GL entry table with for_update here. + last_gl_update = frappe.db.get_value("GL Entry", {}, "modified", for_update=True, wait=False) except frappe.QueryTimeoutError: # wait=False fails immediately if there's an active transaction. last_gl_update = add_to_date(None, seconds=-1)