diff --git a/Coder.Editor/DocumentStore.cs b/Coder.Editor/DocumentStore.cs
index 8d69eab..38b99c4 100644
--- a/Coder.Editor/DocumentStore.cs
+++ b/Coder.Editor/DocumentStore.cs
@@ -61,6 +61,13 @@ public DocumentResult Load(string path)
return DocumentResult.Failed($"Could not read {path}: {ex.Message}");
}
+ // An interrupted save or a newly created file leaves nothing in it, and the deserializer
+ // refuses empty text as a bad argument, which would read to the user as a parse failure.
+ if (string.IsNullOrWhiteSpace(yaml))
+ {
+ return DocumentResult.Failed($"{path} is empty.");
+ }
+
AstNode? root;
try
{
diff --git a/Coder.Test/Editor/CoderEditorAppTests.cs b/Coder.Test/Editor/CoderEditorAppTests.cs
index 562083a..e8f32fd 100644
--- a/Coder.Test/Editor/CoderEditorAppTests.cs
+++ b/Coder.Test/Editor/CoderEditorAppTests.cs
@@ -235,6 +235,27 @@ public void Open_ReportsAFileThatIsNotADocument()
Assert.IsNull(app.DocumentPath);
}
+ ///
+ /// Tests that an empty or whitespace-only file is reported as empty rather than as a document
+ /// the editor cannot parse, since an interrupted save leaves exactly that behind.
+ ///
+ /// What the file holds.
+ [TestMethod]
+ [DataRow("")]
+ [DataRow(" \n")]
+ public void Open_ReportsAnEmptyFile(string content)
+ {
+ DocumentStore store = NewStore();
+ string empty = Path.Combine(root, "empty" + DocumentStore.Extension);
+ File.WriteAllText(empty, content);
+ CoderEditorApp app = NewApp(store);
+
+ Assert.IsFalse(app.Open(empty));
+
+ Assert.AreEqual($"{empty} is empty.", app.Status);
+ Assert.IsNull(app.DocumentPath);
+ }
+
///
/// Tests that a write the filesystem refuses is reported rather than thrown, so a bad
/// destination cannot take the editor down mid-session.