Index: trunk/src/org/openstreetmap/josm/data/validation/tests/SharpAngles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/SharpAngles.java	(revision 18618)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/SharpAngles.java	(revision 18619)
@@ -92,5 +92,9 @@
 
     private void checkAngle(Node node1, Node node2, Node node3, int i, Way way, boolean last) {
-        if (node1 == null || node2 == null || node3 == null) return;
+        if (node1 == null || !node1.isLatLonKnown()
+            || node2 == null || !node2.isLatLonKnown()
+            || node3 == null || !node3.isLatLonKnown()) {
+            return;
+        }
         EastNorth n1 = node1.getEastNorth();
         EastNorth n2 = node2.getEastNorth();
Index: trunk/test/unit/org/openstreetmap/josm/data/validation/tests/SharpAnglesTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/validation/tests/SharpAnglesTest.java	(revision 18618)
+++ trunk/test/unit/org/openstreetmap/josm/data/validation/tests/SharpAnglesTest.java	(revision 18619)
@@ -2,16 +2,27 @@
 package org.openstreetmap.josm.data.validation.tests;
 
-import org.junit.Assert;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.openstreetmap.josm.JOSMFixture;
 import org.openstreetmap.josm.TestUtils;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 
 /**
  * JUnit Test of the Sharp Angles validation test.
  */
+@BasicPreferences
 class SharpAnglesTest {
     private SharpAngles angles;
@@ -38,5 +49,5 @@
         way.addNode(way.firstNode());
         angles.visit(way);
-        Assert.assertEquals(0, angles.getErrors().size());
+        assertEquals(0, angles.getErrors().size());
     }
 
@@ -52,5 +63,5 @@
         angles.setMaxLength(Double.MAX_VALUE);
         angles.visit(way);
-        Assert.assertEquals(1, angles.getErrors().size());
+        assertEquals(1, angles.getErrors().size());
     }
 
@@ -67,5 +78,5 @@
         angles.setMaxLength(Double.MAX_VALUE);
         angles.visit(way);
-        Assert.assertEquals(2, angles.getErrors().size());
+        assertEquals(2, angles.getErrors().size());
     }
 
@@ -79,5 +90,5 @@
                 new Node(new LatLon(0.2, 0.3)), new Node(new LatLon(0.3, 0.1)));
         angles.visit(way);
-        Assert.assertEquals(0, angles.getErrors().size());
+        assertEquals(0, angles.getErrors().size());
     }
 
@@ -98,5 +109,5 @@
         way.addNode(way.firstNode());
         angles.visit(way);
-        Assert.assertEquals(0, angles.getErrors().size());
+        assertEquals(0, angles.getErrors().size());
     }
 
@@ -111,21 +122,54 @@
         angles.setMaxLength(Double.MAX_VALUE);
         angles.visit(way);
-        Assert.assertEquals(1, angles.getErrors().size());
+        assertEquals(1, angles.getErrors().size());
         angles.getErrors().clear();
 
         way.put("highway", "rest_area");
         angles.visit(way);
-        Assert.assertEquals(0, angles.getErrors().size());
+        assertEquals(0, angles.getErrors().size());
 
         way.put("highway", "residential");
         angles.visit(way);
-        Assert.assertEquals(1, angles.getErrors().size());
+        assertEquals(1, angles.getErrors().size());
         angles.getErrors().clear();
         way.put("area", "yes");
         angles.visit(way);
-        Assert.assertEquals(0, angles.getErrors().size());
+        assertEquals(0, angles.getErrors().size());
         way.put("area", "no");
         angles.visit(way);
-        Assert.assertEquals(1, angles.getErrors().size());
+        assertEquals(1, angles.getErrors().size());
+    }
+
+    static Stream<Arguments> testNonRegression22600() {
+        return Stream.of(
+                // All invalid nodes
+                Arguments.of(new Node(), new Node(), new Node()),
+                // Single valid nodes
+                Arguments.of(new Node(LatLon.SOUTH_POLE), new Node(), new Node()),
+                Arguments.of(new Node(), new Node(LatLon.ZERO), new Node()),
+                Arguments.of(new Node(), new Node(), new Node(LatLon.NORTH_POLE)),
+                // Two valid nodes
+                Arguments.of(new Node(), new Node(LatLon.ZERO), new Node(LatLon.NORTH_POLE)),
+                Arguments.of(new Node(LatLon.SOUTH_POLE), new Node(LatLon.ZERO), new Node()),
+                Arguments.of(new Node(LatLon.SOUTH_POLE), new Node(), new Node(LatLon.NORTH_POLE)),
+                // All valid nodes
+                Arguments.of(new Node(LatLon.SOUTH_POLE), new Node(LatLon.ZERO), new Node(LatLon.NORTH_POLE))
+        );
+    }
+
+    /**
+     * Non-regression test for #22600: NPE: Cannot invoke {@link EastNorth#isValid()} because "common" is null
+     */
+    @ParameterizedTest
+    @MethodSource
+    void testNonRegression22600(Node node1, Node node2, Node node3) {
+        Way invalidWay = new Way();
+        invalidWay.put("highway", "trunk");
+        invalidWay.setNodes(Arrays.asList(node1, node2, node3));
+        assertDoesNotThrow(() -> this.angles.visit(invalidWay));
+        for (Node node : invalidWay.getNodes()) {
+            node.setCoor(LatLon.ZERO);
+            assertDoesNotThrow(() -> this.angles.visit(invalidWay));
+        }
     }
 }
