Index: src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(revision 18985)
+++ src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java	(working copy)
@@ -38,7 +38,6 @@
 import org.openstreetmap.josm.data.UndoRedoHandler;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.ILatLon;
-import org.openstreetmap.josm.data.osm.DataIntegrityProblemException;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -81,6 +80,7 @@
     private long mouseDownTime;
     private transient WaySegment selectedSegment;
     private transient Node selectedNode;
+    private transient Command lastCommandOnUndoStack;
     private Color mainColor;
     private transient Stroke mainStroke;
 
@@ -331,6 +331,7 @@
         map.keyDetector.removeModifierExListener(this);
         this.selectedNode = null;
         this.selectedSegment = null;
+        this.lastCommandOnUndoStack = null;
         super.exitMode();
     }
 
@@ -401,6 +402,7 @@
 
         // If nothing gets caught, stay in select mode
         if (selectedSegment == null && selectedNode == null) return;
+        lastCommandOnUndoStack = UndoRedoHandler.getInstance().getLastCommand();
 
         if (selectedNode != null) {
             if (ctrl || nodeDragWithoutCtrl) {
@@ -545,13 +547,8 @@
                     // double click adds a new node
                     addNewNode(e);
                 } else if (e.getPoint().distance(initialMousePos) > initialMoveThreshold && newN1en != null && selectedSegment != null) {
-                    try {
-                        // main extrusion commands
-                        performExtrusion();
-                    } catch (DataIntegrityProblemException ex) {
-                        // Can occur if calling undo while extruding, see #12870
-                        Logging.error(ex);
-                    }
+                    // main extrusion commands
+                    performExtrusion();
                 }
             } else if (mode == Mode.translate || mode == Mode.translate_node) {
                 //Commit translate
@@ -566,6 +563,7 @@
             mapView.setNewCursor(ctrl ? cursorTranslate : alt ? cursorCreateNew : shift ? cursorCreateNodes : cursor, this);
             mapView.removeTemporaryLayer(this);
             selectedSegment = null;
+            lastCommandOnUndoStack = null;
             moveCommand = null;
             mode = Mode.select;
             dualAlignSegmentCollapsed = false;
@@ -638,7 +636,13 @@
      * Uses {@link #newN1en}, {@link #newN2en} calculated by {@link #calculateBestMovementAndNewNodes}
      */
     private void performExtrusion() {
+        // sanity checks, see #23447 and #12870: don't try to extrude when user press undo
+        if (lastCommandOnUndoStack != UndoRedoHandler.getInstance().getLastCommand())
+            return;
         DataSet ds = getLayerManager().getEditDataSet();
+        if (ds.getPrimitiveById(selectedSegment.getWay()) == null || !selectedSegment.isUsable())
+            return;
+
         // create extrusion
         Collection<Command> cmds = new LinkedList<>();
         Way wnew = new Way(selectedSegment.getWay());
