diff --git a/src/cal_tools/tools.py b/src/cal_tools/tools.py
index 0760d48a70145ab5ae5237a8a9088e8290af624c..e0eb543da3838af1a09ff985084a93236f726c40 100644
--- a/src/cal_tools/tools.py
+++ b/src/cal_tools/tools.py
@@ -813,13 +813,23 @@ def module_index_to_qm(index: int, total_modules: int = 16):
 
 
 def recursive_update(target: dict, source: dict):
+    """Recursively merge source into target, checking for conflicts
+
+    Conflicting entries will not be copied to target. Returns True if any
+    conflicts were found.
+    """
+    conflict = False
     for k, v2 in source.items():
         v1 = target.get(k, None)
         if isinstance(v1, dict) and isinstance(v2, dict):
-            recursive_update(v1, v2)
+            conflict = recursive_update(v1, v2) or conflict
+        elif (v1 is not None) and (v1 != v2):
+            conflict = True
         else:
             target[k] = v2
 
+    return conflict
+
 class CalibrationMetadata(dict):
     """Convenience class: dictionary stored in metadata YAML file
 
@@ -868,14 +878,19 @@ class CalibrationMetadata(dict):
     def gather_fragments(self):
         """Merge in fragments saved by add_fragment(), then delete them"""
         frag_files = list(self._yaml_fn.parent.glob('metadata_frag_*.yml'))
+        to_delete = []
         for fn in frag_files:
             with fn.open("r") as fd:
                 data = yaml.safe_load(fd)
-                recursive_update(self, data)
+                if recursive_update(self, data):
+                    print(f"{fn} contained conflicting metadata. "
+                          f"This file will be left for debugging")
+                else:
+                    to_delete.append(fn)
 
         self.save()
 
-        for fn in frag_files:
+        for fn in to_delete:
             fn.unlink()