Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java	(revision 11131)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java	(revision 11132)
@@ -15,4 +15,5 @@
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -34,4 +35,5 @@
 import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.tools.AlphanumComparator;
 import org.openstreetmap.josm.tools.Destroyable;
 import org.openstreetmap.josm.tools.ListenerList;
@@ -180,6 +182,8 @@
             = errors.stream().filter(filterToUse).collect(
                     Collectors.groupingBy(TestError::getSeverity, () -> new EnumMap<>(Severity.class),
-                            Collectors.groupingBy(TestError::getMessage,
-                                    Collectors.groupingBy(e -> e.getDescription() == null ? "" : e.getDescription()
+                            Collectors.groupingBy(TestError::getMessage, () -> new TreeMap<>(AlphanumComparator.getInstance()),
+                                    Collectors.groupingBy(e -> e.getDescription() == null ? "" : e.getDescription(),
+                                            () -> new TreeMap<>(AlphanumComparator.getInstance()),
+                                            Collectors.toList()
                                     ))));
 
@@ -230,4 +234,6 @@
                     if (groupNode != null) {
                         msg = tr("{0} ({1})", description, errors.size());
+                    } else if (description == null || description.isEmpty()) {
+                        msg = tr("{0} ({1})", message, errors.size());
                     } else {
                         msg = tr("{0} - {1} ({2})", message, description, errors.size());
Index: /trunk/test/unit/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanelTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanelTest.java	(revision 11131)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanelTest.java	(revision 11132)
@@ -9,4 +9,5 @@
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Set;
@@ -47,9 +48,21 @@
                         .build(),
                 TestError.builder(null, Severity.WARNING, 0)
-                        .message("warn")
+                        .message("warn", "foo")
+                        .primitives(new Node(2))
+                        .build(),
+                TestError.builder(null, Severity.WARNING, 0)
+                        .message("warn", "bar")
                         .primitives(new Node(2))
                         .build())));
         assertNotNull(vtp);
-        assertEquals(2, vtp.getErrors().size());
+        final Enumeration nodes = vtp.getRoot().breadthFirstEnumeration();
+        assertEquals("", nodes.nextElement().toString());
+        assertEquals("Errors (1)", nodes.nextElement().toString());
+        assertEquals("Warnings (2)", nodes.nextElement().toString());
+        assertEquals("err (1)", nodes.nextElement().toString());
+        assertEquals("warn (2)", nodes.nextElement().toString());
+        nodes.nextElement();
+        assertEquals("bar (1)", nodes.nextElement().toString());
+        assertEquals("foo (1)", nodes.nextElement().toString());
         vtp.setVisible(true);
         vtp.setVisible(false);
