The route decides whether the target changed with request.body.targetSnapshot !== device.targetSnapshotId, which compares the snapshot hashid with the numeric id, so it is always true.
Steps to reproduce
- Set a snapshot as a device's target.
- Set the same snapshot again.
The second call sends another update command to the device and writes another pair of device.snapshot.deployed and device.snapshot.target-set audit entries. A device in developer mode gets a forced update, which discards any unsaved changes in the device editor.
Expected
Setting the current target again is a no-op.
Reference
forge/routes/api/device.js:736. The UI avoids it by checking the current target first (SnapshotDetailsDrawer.vue:295), and so does the MCP tool in #8811.
The route decides whether the target changed with
request.body.targetSnapshot !== device.targetSnapshotId, which compares the snapshot hashid with the numeric id, so it is always true.Steps to reproduce
The second call sends another update command to the device and writes another pair of
device.snapshot.deployedanddevice.snapshot.target-setaudit entries. A device in developer mode gets a forced update, which discards any unsaved changes in the device editor.Expected
Setting the current target again is a no-op.
Reference
forge/routes/api/device.js:736. The UI avoids it by checking the current target first (SnapshotDetailsDrawer.vue:295), and so does the MCP tool in #8811.