Index: /trunk/src/org/openstreetmap/josm/actions/SaveActionBase.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/SaveActionBase.java	(revision 7203)
+++ /trunk/src/org/openstreetmap/josm/actions/SaveActionBase.java	(revision 7204)
@@ -56,6 +56,16 @@
     }
 
-    public static boolean doSave(Layer layer, File file) {
-        if(!layer.checkSaveConditions())
+    /**
+     * Saves a layer to a given file.
+     * @param layer The layer to save
+     * @param file The destination file
+     * @param checkSaveConditions if {@code true}, checks preconditions before saving. Set it to {@code false} to skip it
+     * if preconditions have already been checked (as this check can prompt UI dialog in EDT it may be best in some cases
+     * to do it earlier).
+     * @return {@code true} if the layer has been successfully saved, {@code false} otherwise
+     * @since 7204
+     */
+    public static boolean doSave(Layer layer, File file, boolean checkSaveConditions) {
+        if (checkSaveConditions && !layer.checkSaveConditions())
             return false;
         return doInternalSave(layer, file);
Index: /trunk/src/org/openstreetmap/josm/gui/io/SaveLayerInfo.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayerInfo.java	(revision 7203)
+++ /trunk/src/org/openstreetmap/josm/gui/io/SaveLayerInfo.java	(revision 7204)
@@ -16,4 +16,5 @@
     /** the osm data layer */
     private OsmDataLayer layer;
+    private boolean doCheckSaveConditions;
     private boolean doSaveToFile;
     private boolean doUploadToServer;
@@ -23,5 +24,5 @@
 
     /**
-     *
+     * Constructs a new {@code SaveLayerInfo}.
      * @param layer the layer. Must not be null.
      * @throws IllegalArgumentException thrown if layer is null
@@ -30,4 +31,5 @@
         CheckParameterUtil.ensureParameterNotNull(layer, "layer");
         this.layer = layer;
+        this.doCheckSaveConditions = true;
         this.doSaveToFile = layer.requiresSaveToFile();
         this.doUploadToServer = layer.requiresUploadToServer() && !layer.isUploadDiscouraged();
@@ -42,4 +44,24 @@
     public OsmDataLayer getLayer() {
         return layer;
+    }
+
+    /**
+     * Replies true if preconditions should be checked before saving; false, otherwise
+     *
+     * @return true if preconditions should be checked before saving; false, otherwise
+     * @since 7204
+     */
+    public boolean isDoCheckSaveConditions() {
+        return doCheckSaveConditions;
+    }
+
+    /**
+     * Sets whether preconditions should be checked before saving
+     *
+     * @param doCheckSaveConditions true to check save preconditions; false, to skip checking
+     * @since 7204
+     */
+    public void setDoCheckSaveConditions(boolean doCheckSaveConditions) {
+        this.doCheckSaveConditions = doCheckSaveConditions;
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/io/SaveLayerTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayerTask.java	(revision 7203)
+++ /trunk/src/org/openstreetmap/josm/gui/io/SaveLayerTask.java	(revision 7204)
@@ -49,5 +49,5 @@
         try {
             parentMonitor.subTask(tr("Saving layer to ''{0}'' ...", layerInfo.getFile().toString()));
-            if (!SaveAction.doSave(layerInfo.getLayer(), layerInfo.getFile())) {
+            if (!SaveAction.doSave(layerInfo.getLayer(), layerInfo.getFile(), layerInfo.isDoCheckSaveConditions())) {
                 setFailed(true);
                 return;
Index: /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java	(revision 7203)
+++ /trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java	(revision 7204)
@@ -506,5 +506,12 @@
                     continue;
                 }
-                currentTask= new SaveLayerTask(layerInfo, monitor);
+                // Check save preconditions earlier to avoid a blocking reentring call to EDT (see #10086)
+                if (layerInfo.isDoCheckSaveConditions()) {
+                    if (!layerInfo.getLayer().checkSaveConditions()) {
+                        continue;
+                    }
+                    layerInfo.setDoCheckSaveConditions(false);
+                }
+                currentTask = new SaveLayerTask(layerInfo, monitor);
                 currentFuture = worker.submit(currentTask);
 
Index: /trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 7203)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 7204)
@@ -1,4 +1,3 @@
 // License: GPL. See LICENSE file for details.
-
 package org.openstreetmap.josm.gui.layer;
 
@@ -28,4 +27,5 @@
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -78,4 +78,5 @@
 import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.gui.widgets.JosmTextArea;
 import org.openstreetmap.josm.tools.DateUtils;
@@ -750,27 +751,39 @@
     public boolean checkSaveConditions() {
         if (isDataSetEmpty()) {
-            ExtendedDialog dialog = new ExtendedDialog(
-                    Main.parent,
-                    tr("Empty document"),
-                    new String[] {tr("Save anyway"), tr("Cancel")}
-            );
-            dialog.setContent(tr("The document contains no data."));
-            dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
-            dialog.showDialog();
-            if (dialog.getValue() != 1) return false;
+            if (1 != GuiHelper.runInEDTAndWaitAndReturn(new Callable<Integer>() {
+                @Override
+                public Integer call() {
+                    ExtendedDialog dialog = new ExtendedDialog(
+                            Main.parent,
+                            tr("Empty document"),
+                            new String[] {tr("Save anyway"), tr("Cancel")}
+                    );
+                    dialog.setContent(tr("The document contains no data."));
+                    dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
+                    return dialog.showDialog().getValue();
+                }
+            })) {
+                return false;
+            }
         }
 
         ConflictCollection conflicts = getConflicts();
         if (conflicts != null && !conflicts.isEmpty()) {
-            ExtendedDialog dialog = new ExtendedDialog(
-                    Main.parent,
-                    /* I18N: Display title of the window showing conflicts */
-                    tr("Conflicts"),
-                    new String[] {tr("Reject Conflicts and Save"), tr("Cancel")}
-            );
-            dialog.setContent(tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"));
-            dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
-            dialog.showDialog();
-            if (dialog.getValue() != 1) return false;
+            if (1 != GuiHelper.runInEDTAndWaitAndReturn(new Callable<Integer>() {
+                @Override
+                public Integer call() {
+                    ExtendedDialog dialog = new ExtendedDialog(
+                            Main.parent,
+                            /* I18N: Display title of the window showing conflicts */
+                            tr("Conflicts"),
+                            new String[] {tr("Reject Conflicts and Save"), tr("Cancel")}
+                    );
+                    dialog.setContent(tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"));
+                    dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
+                    return dialog.showDialog().getValue();
+                }
+            })) {
+                return false;
+            }
         }
         return true;
Index: /trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java	(revision 7203)
+++ /trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java	(revision 7204)
@@ -22,4 +22,7 @@
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
 
 import javax.swing.GrayFilter;
@@ -68,4 +71,10 @@
     }
 
+    /**
+     * Executes asynchronously a runnable in
+     * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>.
+     * @param task The runnable to execute
+     * @see SwingUtilities#invokeLater
+     */
     public static void runInEDT(Runnable task) {
         if (SwingUtilities.isEventDispatchThread()) {
@@ -76,4 +85,10 @@
     }
 
+    /**
+     * Executes synchronously a runnable in
+     * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>.
+     * @param task The runnable to execute
+     * @see SwingUtilities#invokeAndWait
+     */
     public static void runInEDTAndWait(Runnable task) {
         if (SwingUtilities.isEventDispatchThread()) {
@@ -84,4 +99,32 @@
             } catch (InterruptedException | InvocationTargetException e) {
                 Main.error(e);
+            }
+        }
+    }
+
+    /**
+     * Executes synchronously a callable in
+     * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>
+     * and return a value.
+     * @param callable The callable to execute
+     * @return The computed result
+     * @since 7204
+     */
+    public static <V> V runInEDTAndWaitAndReturn(Callable<V> callable) {
+        if (SwingUtilities.isEventDispatchThread()) {
+            try {
+                return callable.call();
+            } catch (Exception e) {
+                Main.error(e);
+                return null;
+            }
+        } else {
+            FutureTask<V> task = new FutureTask<V>(callable);
+            SwingUtilities.invokeLater(task);
+            try {
+                return task.get();
+            } catch (InterruptedException | ExecutionException e) {
+                Main.error(e);
+                return null;
             }
         }
