Index: src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java
===================================================================
--- src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(revision 17177)
+++ src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java	(working copy)
@@ -327,7 +327,7 @@
             jobs.add(ecs.submit(new Fetcher(type, extractIdPackage(toFetch), progressMonitor)));
         }
         // Run the fetchers
-        for (int i = 0; i < jobs.size() && !isCanceled(); i++) {
+        for (int i = 0; i < jobs.size() && !isCanceled() && !progressMonitor.isCanceled(); i++) {
             progressMonitor.subTask(msg + "... " + progressMonitor.getTicks() + '/' + progressMonitor.getTicksCount());
             try {
                 FetchResult result = ecs.take().get();
@@ -348,6 +348,8 @@
                 Logging.error(e);
             }
         }
+        if (progressMonitor.isCanceled() && !isCanceled())
+            cancel();
         exec.shutdown();
         // Cancel requests if the user chose to
         if (isCanceled()) {
@@ -441,6 +443,8 @@
      */
     private void downloadRelations(ProgressMonitor progressMonitor) throws OsmTransferException {
         Set<Long> toDownload = new LinkedHashSet<>(relations);
+        if (toDownload.isEmpty())
+            return;
         fetchPrimitives(toDownload, OsmPrimitiveType.RELATION, progressMonitor);
         if (!recurseDownRelations) {
             return;
@@ -450,6 +454,11 @@
             if (!r.isVisible())
                 toDownload.remove(r.getUniqueId());
         }
+        // remember downloaded relations
+        DataSet invisible = new DataSet();
+        new DataSetMerger(invisible, outputDataSet).merge();
+        // clear dataset so that merge() doesn't find the incomplete relation(s)
+        outputDataSet.clear();
         // fetch full info for all visible relations
         for (long id : toDownload) {
             if (isCanceled())
@@ -458,6 +467,8 @@
             DataSet ds = reader.parseOsm(progressMonitor.createSubTaskMonitor(1, false));
             merge(ds);
         }
+        // merge possibly invisible relations back
+        new DataSetMerger(outputDataSet, invisible).merge();
     }
 
     /**
@@ -585,9 +596,8 @@
                         Logging.info(tr("Server replied with response code 404, retrying with an individual request for each object."));
                         return singleGetIdPackage(type, pkg, progressMonitor);
                     }
-                } else {
-                    throw e;
                 }
+                throw e;
             }
         }
 
