diff --git a/src/Project.cpp b/src/Project.cpp
index ec8c38f905ab33d01fbc15da94072e3494563a34..a1a1dd996606f5d673efaf9b1789b4608f11d48e 100644
--- a/src/Project.cpp
+++ b/src/Project.cpp
@@ -3873,15 +3873,24 @@ bool AudacityProject::Save(bool overwrite /* = true */ ,
    // Write the .aup now, before DirManager::SetProject,
    // because it's easier to clean up the effects of successful write of .aup
    // followed by failed SetProject, than the other way about.
-   // And that cleanup is done by the destructor of saveFile, if Commit() is
+   // And that cleanup is done by the destructor of saveFile, if PostCommit() is
    // not done.
    // (SetProject, when it fails, cleans itself up.)
    XMLFileWriter saveFile{ mFileName, _("Error Saving Project") };
    success = GuardedCall< bool >( [&] {
-      WriteXMLHeader(saveFile);
-      WriteXML(saveFile, bWantSaveCompressed);
-      return true;
-   } );
+         WriteXMLHeader(saveFile);
+         WriteXML(saveFile, bWantSaveCompressed);
+         // Flushes files, forcing space exhaustion errors before trying
+         // SetProject():
+         saveFile.PreCommit();
+         return true;
+      },
+      MakeSimpleGuard(false),
+      // Suppress the usual error dialog for failed write,
+      // which is redundant here:
+      [](void*){}
+   );
+
    if (!success)
       return false;
 
@@ -3920,9 +3929,14 @@ bool AudacityProject::Save(bool overwrite /* = true */ ,
 
    // Commit the writing of the .aup only now, after we know that the _data
    // folder also saved with no problems.
+   // Error recovery in case this fails might not be correct -- there is no
+   // provision to undo the effects of SetProject -- but it is very unlikely
+   // that this will happen:  only renaming and removing of files happens,
+   // not writes that might exhaust space.  So DO give a second dialog in
+   // case the unusual happens.
    success = success && GuardedCall< bool >( [&] {
-      saveFile.Commit();
-      return true;
+         saveFile.PostCommit();
+         return true;
    } );
 
    if (!success)
diff --git a/src/xml/XMLWriter.cpp b/src/xml/XMLWriter.cpp
index dd1904c024ca1fdfb8b884656f0a0aa40f0533a4..a969b0b7919a6ecd108635ebb3650b6ed9d20b64 100644
--- a/src/xml/XMLWriter.cpp
+++ b/src/xml/XMLWriter.cpp
@@ -313,14 +313,25 @@ XMLFileWriter::~XMLFileWriter()
 
 void XMLFileWriter::Commit()
 // may throw
+{
+   PreCommit();
+   PostCommit();
+}
+
+void XMLFileWriter::PreCommit()
+// may throw
 {
    while (mTagstack.GetCount()) {
       EndTag(mTagstack[0]);
    }
 
-   auto tempPath = GetName();
    CloseWithoutEndingTags();
+}
 
+void XMLFileWriter::PostCommit()
+// may throw
+{
+   auto tempPath = GetName();
    if (mKeepBackup) {
       if (! mBackupFile.Close() ||
           ! wxRenameFile( mOutputPath, mBackupName ) )
diff --git a/src/xml/XMLWriter.h b/src/xml/XMLWriter.h
index e8262d7b00182f2b460d5fb80442e17f343b20b6..11cb791cb2645a0f03ea2cab95e2b422771ae008 100644
--- a/src/xml/XMLWriter.h
+++ b/src/xml/XMLWriter.h
@@ -86,8 +86,16 @@ class AUDACITY_DLL_API XMLFileWriter final : private wxFFile, public XMLWriter {
    /// Close all tags and then close the file.
    /// Might throw.  If not, then create
    /// or modify the file at the output path.
+   /// Composed of two steps, PreCommit() and PostCommit()
    void Commit();
 
+   /// Does the part of Commit that might fail because of exhaustion of space
+   void PreCommit();
+
+   /// Does other parts of Commit that are not likely to fail for exhaustion
+   /// of space, but might for other reasons
+   void PostCommit();
+
    /// Write to file. Might throw.
    void Write(const wxString &data) override;