Random Failure: Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction

I am trying to solve this error

frappe.exceptions.ValidationError: Incorrect number of General Ledger Entries found.
You might have selected a wrong Account in the transaction.

It happens unpredictably when creating Stock Entry records in a loop.

I understand that the purpose of this error trap …

… is to ensure that every GL entry will be defined by a matched debit credit pair.

The problem I am encountering arises from creating a number of Stock Entry records in a Python loop. However I have also seen it happen when I create the Stock Entry doc manually.

I am trying to track down the root cause in …

… but it is very hard to understand what goes on in there.

What I do see is the gl_map list will contain only one half of the transaction, just before the failure, whereas in all prior iterations of the loop gl_map has both halves

I have found no pattern in when and why it fails. Sometimes it will loop only once or twice. Sometimes it will process all and complete successfully.

My code to create the Stock Entry:

def createStockEntry(spec):
    body = {
      "doctype": "Stock Entry",
      "docstatus": 0,
      "stock_entry_type": "Material Transfer",
      "title": "Move {}xx to {}".format(spec.sn_block, spec.tgt),
      "items": [
        {
          "qty": spec.qty,
          "item_code": "Deluxe Terraforming Robot",
          "s_warehouse": spec.src,
          "t_warehouse": spec.tgt,
          "serial_no": spec.serial_no
        }
      ]
    }

    stock_entry = frappe.get_doc(body)

    stock_entry.save()
    stock_entry.submit()

    LG("        Commit: {} ==> {}".format(spec.sn_block, spec.tgt))
    frappe.db.commit()

My Questions:
Is this a known issue?
Is it a race condition ?
Are there known procedural techniques to ensure timing is not a problem?


Full error log:

17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/returnable/returnable/returnable/doctype/returnable/initialize_stock.py", line 106, in createStockEntry
17:26:16 web.1            |     stock_entry.submit()
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 929, in submit
17:26:16 web.1            |     self._submit()
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 918, in _submit
17:26:16 web.1            |     self.save()
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 285, in save
17:26:16 web.1            |     return self._save(*args, **kwargs)
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 337, in _save
17:26:16 web.1            |     self.run_post_save_methods()
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 997, in run_post_save_methods
17:26:16 web.1            |     self.run_method("on_submit")
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 859, in run_method
17:26:16 web.1            |     out = Document.hook(fn)(self, *args, **kwargs)
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 1148, in composer
17:26:16 web.1            |     return composed(self, method, *args, **kwargs)
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 1131, in runner
17:26:16 web.1            |     add_to_return_value(self, fn(self, *args, **kwargs))
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/model/document.py", line 853, in <lambda>
17:26:16 web.1            |     fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py", line 102, in on_submit
17:26:16 web.1            |     self.make_gl_entries()
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/erpnext/erpnext/controllers/stock_controller.py", line 45, in make_gl_entries
17:26:16 web.1            |     make_gl_entries(gl_entries, from_repost=from_repost)
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/erpnext/erpnext/accounts/general_ledger.py", line 23, in make_gl_entries
17:26:16 web.1            |     frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction."))
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/__init__.py", line 432, in throw
17:26:16 web.1            |     msgprint(msg, raise_exception=exc, title=title, indicator='red', is_minimizable=is_minimizable, wide=wide, as_list=as_list)
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/__init__.py", line 411, in msgprint
17:26:16 web.1            |     _raise_exception()
17:26:16 web.1            |   File "/home/erpdev/frappe-bench-DELS/apps/frappe/frappe/__init__.py", line 365, in _raise_exception
17:26:16 web.1            |     raise raise_exception(msg)
17:26:16 web.1            | frappe.exceptions.ValidationError: Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction.

Installed Apps:
ERPNext: v13.6.0 (version-13)
Frappe Framework: v13.6.0 (version-13)

Ubuntu 20.04.2 LTS

erpdev@loso:~$ free -h
              total        used        free      shared  buff/cache   available
Mem:          1.9Gi       1.7Gi       117Mi       2.0Mi       132Mi       105Mi
Swap:         1.0Gi       588Mi       434Mi
erpdev@loso:~$ 
1 Like

I finally tracked this down.

The randomness was only apparent, not real. Just one out of numerous Warehouses was linked to an account which is somehow illegitimate in accounting practices.

5 - Costs and Outlay
5.1 - Costs
5.1.1 - Direct Costs
5.1.1.06 - Stock Adjustments (AcctType=Stock Adjustment, RootType=Expense)

Not being an accountant, I have no idea why that is not allowed

2 Likes