Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 14848)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java	(revision 14849)
@@ -63,4 +63,5 @@
 import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.io.OsmTransferException;
@@ -610,5 +611,5 @@
         protected void fixError(TestError error) throws InterruptedException, InvocationTargetException {
             if (error.isFixable()) {
-                if (error.getPrimitives().stream().noneMatch(OsmPrimitive::isDeleted)) {
+                if (error.getPrimitives().stream().noneMatch(p -> p.isDeleted() || p.getDataSet() == null)) {
                     final Command fixCommand = error.getFix();
                     if (fixCommand != null) {
@@ -632,4 +633,5 @@
                 int i = 0;
                 SwingUtilities.invokeAndWait(ds::beginUpdate);
+                tree.setResetScheduled();
                 try {
                     for (TestError error: testErrors) {
@@ -651,5 +653,4 @@
                     }
                     invalidateValidatorLayers();
-                    tree.resetErrors();
                 });
             } catch (InterruptedException e) {
@@ -663,4 +664,5 @@
                     tryUndo();
                 }
+                GuiHelper.runInEDTAndWait(tree::resetErrors);
                 monitor.finishTask();
             }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java	(revision 14848)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java	(revision 14849)
@@ -81,5 +81,8 @@
     private transient Set<? extends OsmPrimitive> filter;
 
-    private final ListenerList<Runnable> invalidationListeners = ListenerList.create();
+    private final transient ListenerList<Runnable> invalidationListeners = ListenerList.create();
+
+    /** if true, buildTree() does nothing */
+    private boolean resetScheduled;
 
     /**
@@ -148,4 +151,6 @@
      */
     public void buildTree() {
+        if (resetScheduled)
+            return;
         final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
 
@@ -402,4 +407,6 @@
      */
     public void resetErrors() {
+        resetScheduled = false;
+        filterRemovedPrimitives();
         setErrors(new ArrayList<>(errors));
     }
@@ -481,7 +488,6 @@
     @Override public void primitivesRemoved(PrimitivesRemovedEvent event) {
         // Remove purged primitives (fix #8639)
-        if (errors != null) {
-            final Set<? extends OsmPrimitive> deletedPrimitives = new HashSet<>(event.getPrimitives());
-            errors.removeIf(error -> error.getPrimitives().stream().anyMatch(deletedPrimitives::contains));
+        if (filterRemovedPrimitives()) {
+            buildTree();
         }
     }
@@ -512,5 +518,26 @@
 
     @Override public void dataChanged(DataChangedEvent event) {
-        // Do nothing
-    }
+        if (filterRemovedPrimitives()) {
+            buildTree();
+        }
+    }
+
+    /**
+     * Can be called to suppress execution of buildTree() while doing multiple updates. Caller must
+     * call resetErrors() to end this state.
+     * @since 14848
+     */
+    public void setResetScheduled() {
+        resetScheduled = true;
+    }
+
+    /**
+     * Remove errors which refer to removed or purged primitives.
+     * @return true if error list was changed
+     */
+    private boolean filterRemovedPrimitives() {
+        return errors != null && errors.removeIf(
+                error -> error.getPrimitives().stream().anyMatch(p -> p.isDeleted() || p.getDataSet() == null));
+    }
+
 }
