Child Table rows vanished when Saving

It is very strange.

This only happens after I do a minor upgrade in version-13.

I have a DocType, which is a Child Table, and is Editable Grid. The fields have 1 row, and in Options I specified 2 other DocType. Originally its name is DIY Icon Type.

Inside DocType User, I use this DIY Icon Type as Table:

The problem is shown in the video below, when I try to save User, all rows in this Table will vanish before saving.

https://files.tourdefarm.com/wl/?id=JFPO6lpbXBQW53Xuq2cVL7zBE5aYh83O

Potential solution:

I created a new DocType with name DIY Icon Type 1, with the same content, pointing to DIY Simple and DIY Video. Everything remain the same. In DocType User, I now use DIY Icon Type 1 instead of DIY Icon Type and perform a Save again.

The result is the same; all rows are still removed before Saving.

I think the problem is the front end.

Can someone share what they think this issue might be?

If you havent made any changes in code that’s causing this. Then the problem is due to permission error. Click on Edit in “Your icons Settings” field. Then enable ignore permissions. Your issue will be resolved.

1 Like

It’s been extremely painful to troubleshoot this… thanks for your help. Let me see if it solves the issue or not

Sorry, it doesn’t work. Same result on the table Your Icons Settings…

Ahhhhhhhhh!

Are you setting the parent value in a script anywhere?
Can you confirm that these records exist in the database after saving?

Unfortunately, no new records was created in tabDIY Simple nor tabDIY Video.

Ahhhhhhhh!

Ah… the /frappe/frappe/public/js/frappe/form/save.js thinks these rows are empty, and it goes clear them!

Strange!

How are those values being populated?

Like this. I’m really out of my wit…


I am not sure, but this is what I can observe…

In save.js, the function remove_empty_rows’ tables.map() will remove the form data I keyed in…

Something fails when save.js tries to validate the data…so it removes the rows as it might detects some errors.

After lengthy, painful debugging, I found out that there is a line in the save.js that is different between working and non-working instances.

Line 68 is from the non-working, newer Frappe/ERPNext, while line 69 is from the working instance, which is a bit older.

Now, the reason why the newly added rows in Child Table vanish is because these records are put into the variable modified_table_fields in the non-working instance; they are not being put into modified_table_fields in the working instance.

Once the rows are in modified_table_fields, the lines below:

modified_table_fields.forEach(field => {
			frm.refresh_field(field);
		});

will remove them in the form.

Now, when I try to use API to retrieve the Child Table, I can’t. The same API call, no change, but now I get frappe.exceptions.PermissionError.

Could this be the source of issue? I don’t have permission, so new entries in the Child Table will be considered blank, so they are removed prior to Saving?

Nice! It seems that the software just demonstrated that it indeed hinders someone without permissions from manipulating a table or object they don’t have permission to change.

So this would increase the trust level one has for the software.

But you might want to check which permissions apply to which object so you know well how to configure these in order to get the permission/lockdown results you want or need.

I had the same issue and solved it by using a promise-based approach: To make sure the database calls are completed before the save operation, it’s good to use promises. This ensures all operations are done sequentially and then update dirty state after updating the values: frm.dirty() marks the form as having changes, and it should be called after you have completed updating all the fields to ensure that the form gets saved correctly.

Child Tables are not available in JS from frappe.db.['orm function'] where orm function is get_list, get_value, etc. You need to create a custom endpoint to load these with @frappe.whitelist()