Index: trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 19125)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 19126)
@@ -261,4 +261,5 @@
                     getProgressMonitor().subTask(
                             trn("Uploading {0} object...", "Uploading {0} objects...", toUpload.getSize(), toUpload.getSize()));
+                    getProgressMonitor().setTicks(0); // needed in 2nd and further loop executions
                     synchronized (this) {
                         writer = new OsmServerWriter();
Index: trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 19125)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 19126)
@@ -6,4 +6,5 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -19,4 +20,5 @@
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.ChangesetClosedException.Source;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
@@ -156,4 +158,5 @@
             List<OsmPrimitive> chunk = new ArrayList<>(chunkSize);
             Iterator<? extends OsmPrimitive> it = primitives.iterator();
+            int maxChunkSize = api.getCapabilities().getMaxChangesetSize();
             int numChunks = (int) Math.ceil((double) primitives.size() / (double) chunkSize);
             int i = 0;
@@ -163,6 +166,5 @@
                 int j = 0;
                 chunk.clear();
-                while (it.hasNext() && j < chunkSize) {
-                    if (canceled) return;
+                while (it.hasNext() && j < chunkSize && processed.size() + j < maxChunkSize) {
                     j++;
                     chunk.add(it.next());
@@ -173,4 +175,8 @@
                                 chunk.size(), i, numChunks, chunk.size()));
                 processed.addAll(api.uploadDiff(chunk, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
+                // see #23738: server will close CS if maximum changeset size was reached
+                if (processed.size() >= maxChunkSize) {
+                    throw new ChangesetClosedException(api.getChangeset().getId(), Instant.now(), Source.UPLOAD_DATA);
+                }
             }
         } finally {
