Error When Adding Sub-Assembly in BOM Creator – "Parent Row Not Found" and Background Job Fails

Hi everyone,

I’m facing a recurring issue while trying to create a BOM using the BOM Creator in ERPNext.

Whenever I add a sub-assembly (semi-finished item), I get the following error message on the screen:

Parent Row not found for 1TESTBOM1

Even though I receive this error, the sub-assembly is still visible in the background (it appears under the product tree). However, when I try to add another sub-assembly after clicking “Rebuild Tree,” the same error appears again.

If I ignore the errors and proceed to submit the BOM, no BOMs are actually created. I checked the background jobs and found that they are failing with a traceback error.

Here’s the traceback:
Traceback (most recent call last):
File “/home/frappe/frappe-bench/env/lib/python3.12/site-packages/rq/worker.py”, line 1428, in perform_job
rv = job.perform()
^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/env/lib/python3.12/site-packages/rq/job.py”, line 1278, in perform
self._result = self._execute()
^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/env/lib/python3.12/site-packages/rq/job.py”, line 1315, in _execute
result = self.func(*self.args, **self.kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/background_jobs.py”, line 222, in execute_job
retval = method(**kwargs)
^^^^^^^^^^^^^^^^
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/manufacturing/doctype/bom_creator/bom_creator.py”, line 256, in create_boms
production_item_wise_rm[(row.fg_item, row.fg_reference_id)][“items”].append(row)
KeyError: (‘MD019A’, ‘sas2bnudkq’)

Any idea why this is happening and how I can resolve it?

Thanks in advance!

Traceback with variables (most recent call last):
File “apps/erpnext/erpnext/manufacturing/doctype/bom_creator/bom_creator.py”, line 263, in create_boms
self.create_bom(fg_item_data, production_item_wise_rm)
self =
production_item_wise_rm = OrderedDict({(‘G24A1’, ‘G24AA1’): {‘items’: [, , , , , , , , , , , , , , , , , row =
reverse_tree = OrderedDict({(‘MU017K’, ‘uqniiavqvs’): {‘items’: , ‘bom_no’: ‘BOM-MU017K-001’, ‘fg_item_data’: }, (‘MU017A’, ‘uqngva1pir’): {‘items’: , ‘bom_no’: ‘BOM-MU017A-001’, ‘fg_item_data’: }, (‘MD014S’, ‘rreamj6htb’): {‘items’: , ‘bom_no’: ‘BOM-MD014S-001’, ‘fg_item_data’: }, (‘MD014A’, ‘rrenpkv1i8’): {‘items’: , ‘bom_no’: ‘BOM-MD014A-001’, ‘fg_item_data’: }, (‘MD018K’, ‘rhjoteihr2’): {‘items’: , ‘bom_no’: ‘’, ‘fg_item_data’: }, (‘MD018A’, ‘rhjp001ct0’): {‘items’: [ d = (‘MD018K’, ‘rhjoteihr2’)
fg_item_data =
File “apps/erpnext/erpnext/manufacturing/doctype/bom_creator/bom_creator.py”, line 326, in create_bom
bom.save(ignore_permissions=True)
self =
row =
production_item_wise_rm = OrderedDict({(‘G24A1’, ‘G24AA1’): {‘items’: [, , , , , , , , , , , , , , , , , bom_creator_item = ‘rhjoteihr2’
bom =
field = ‘buying_price_list’
File “apps/frappe/frappe/model/document.py”, line 378, in save
return self._save(*args, **kwargs)
self =
args = ()
kwargs = {‘ignore_permissions’: True}
File “apps/frappe/frappe/model/document.py”, line 400, in save
return self.insert()
self =
ignore_permissions = True
ignore_version = None
File “apps/frappe/frappe/model/document.py”, line 309, in insert
self.run_before_save_methods()
self =
ignore_permissions = None
ignore_links = None
ignore_if_duplicate = False
ignore_mandatory = None
set_name = None
set_child_names = True
File “apps/frappe/frappe/model/document.py”, line 1136, in run_before_save_methods
self.run_method(“validate”)
self =
File “apps/frappe/frappe/model/document.py”, line 1007, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
self =
method = ‘validate’
args = ()
kwargs = {}
fn = .fn at 0x70c067111f80>
File “apps/frappe/frappe/model/document.py”, line 1367, in composer
return composed(self, method, args, **kwargs)
self =
args = ()
kwargs = {}
hooks = [, ]
method = ‘validate’
doc_events = {'
': {‘on_update’: [‘frappe.desk.notifications.clear_doctype_notifications’, ‘frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions’, ‘frappe.core.doctype.file.utils.attach_files_to_document’, ‘frappe.automation.doctype.assignment_rule.assignment_rule.apply’, ‘frappe.automation.doctype.assignment_rule.assignment_rule.update_due_date’, ‘frappe.core.doctype.user_type.user_type.apply_permissions_for_non_standard_user_type’], ‘after_rename’: [‘frappe.desk.notifications.clear_doctype_notifications’], ‘on_cancel’: [‘frappe.desk.notifications.clear_doctype_notifications’, ‘frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions’, ‘frappe.automation.doctype.assignment_rule.assignment_rule.apply’], ‘on_trash’: [‘frappe.desk.notifications.clear_doctype_notifications’, ‘frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions’], ‘on_update_after_submit’: ['frappe.workflow.doctype.workflow_action.workflow_action.process_w…
handler = ‘erpnext.setup.doctype.transaction_deletion_record.transaction_deletion_record.check_for_running_deletion_job’
composed = .compose…runner at 0x70c067112200>
compose = .compose at 0x70c0671120c0>
f = .fn at 0x70c067111f80>
File “apps/frappe/frappe/model/document.py”, line 1349, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
self =
method = ‘validate’
args = ()
kwargs = {}
add_to_return_value = .add_to_return_value at 0x70c067112020>
fn = .fn at 0x70c067111f80>
hooks = (, )
File “apps/frappe/frappe/model/document.py”, line 1004, in fn
return method_object(*args, **kwargs)
self =
args = ()
kwargs = {}
method_object = >
method = ‘validate’
File “apps/erpnext/erpnext/manufacturing/doctype/bom/bom.py”, line 269, in validate
self.validate_materials()
self =
File “apps/erpnext/erpnext/manufacturing/doctype/bom/bom.py”, line 645, in validate_materials
frappe.throw(
(“Raw Materials cannot be blank.”))
self =
File “apps/frappe/frappe/init.py”, line 609, in throw
msgprint(
msg = ‘Raw Materials cannot be blank.’
exc =
title = None
is_minimizable = False
wide = False
as_list = False
primary_action = None
File “apps/frappe/frappe/init.py”, line 574, in msgprint
_raise_exception()
msg = ‘Raw Materials cannot be blank.’
title = None
raise_exception =
as_table = False
as_list = False
indicator = ‘red’
alert = False
primary_action = None
is_minimizable = False
wide = False
realtime = False
sys =
_raise_exception = ._raise_exception at 0x70c067112340>
inspect =
out = {‘message’: ‘Raw Materials cannot be blank.’, ‘title’: ‘Message’, ‘indicator’: ‘red’, ‘raise_exception’: 1, ‘__frappe_exc_id’: ‘c23a9625d289ce175bed7016689befb9e5e9ee000b29b21202f38353’}
File “apps/frappe/frappe/init.py”, line 525, in _raise_exception
raise exc
exc = ValidationError(‘Raw Materials cannot be blank.’)
inspect =
msg = ‘Raw Materials cannot be blank.’
out = {‘message’: ‘Raw Materials cannot be blank.’, ‘title’: ‘Message’, ‘indicator’: ‘red’, ‘raise_exception’: 1, ‘__frappe_exc_id’: ‘c23a9625d289ce175bed7016689befb9e5e9ee000b29b21202f38353’}
raise_exception =
frappe.exceptions.ValidationError: Raw Materials cannot be blank.