{"record":{"id":"902c79ab4de0e349","repo":"LorisYounger/VPet","slug":"save-data-is-null","errorCode":null,"errorMessage":"Save data is null","messagePattern":"Save data is null","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"VPet-Simulator.Windows/MainWindow.cs","lineNumber":327,"sourceCode":"                    var ds = new List<string>(Directory.GetFiles(ExtensionValue.BaseDirectory + @\"\\Saves\", $\"Save{PrefixSave}_*.lps\")).OrderBy(x =>\n                    {\n                        if (int.TryParse(x.Split('_').Last().Split('.')[0], out int i))\n                            return i;\n                        return 0;\n                    }).ToList();\n                    while (ds.Count > Set.BackupSaveMaxNum)\n                    {\n                        File.Delete(ds[0]);\n                        ds.RemoveAt(0);\n                    }\n\n                    if (File.Exists(ExtensionValue.BaseDirectory + $\"\\\\Saves\\\\Save{PrefixSave}_{st}.lps\"))\n                        File.Delete(ExtensionValue.BaseDirectory + $\"\\\\Saves\\\\Save{PrefixSave}_{st}.lps\");\n\n                    var saveslps = GameSavesData.ToLPS();\n                    var savesdata = saveslps.ToString();\n                    if (savesdata == null)\n                        throw new Exception(\"Save data is null\");\n\n\n                    int hash = Math.Abs(saveslps.GetHashCode() % 255);\n                    if (File.Exists(ExtensionValue.BaseDirectory + $\"\\\\Saves_BKP\\\\Save{PrefixSave}_{hash:X}.lps\"))\n                        File.Delete(ExtensionValue.BaseDirectory + $\"\\\\Saves_BKP\\\\Save{PrefixSave}_{hash:X}.lps\");\n\n                    //存档\n                    File.WriteAllText(ExtensionValue.BaseDirectory + $\"\\\\Saves\\\\Save{PrefixSave}_{st}.lps\", savesdata);\n                    //备份\n                    File.WriteAllText(ExtensionValue.BaseDirectory + $\"\\\\Saves_BKP\\\\Save{PrefixSave}_{hash:X}.lps\", savesdata);\n\n                    if (File.Exists(ExtensionValue.BaseDirectory + @\"\\Save.lps\"))\n                    {\n                        if (File.Exists(ExtensionValue.BaseDirectory + @\"\\Save.bkp\"))\n                            File.Delete(ExtensionValue.BaseDirectory + @\"\\Save.bkp\");\n                        File.Move(ExtensionValue.BaseDirectory + @\"\\Save.lps\", ExtensionValue.BaseDirectory + @\"\\Save.bkp\");\n                    }\n","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/LorisYounger/VPet/blob/ffb9cc2a856244a0f91aa5ecf10d097bcdd4954f/VPet-Simulator.Windows/MainWindow.cs#L309-L345","documentation":"MainWindow.Save serializes GameSavesData to LPS and asserts the resulting string is non-null before writing the save file, throwing a generic Exception if it is null. This is a defensive invariant protecting the save routine from silently writing nothing.","triggerScenarios":"Save (called by Restart_Closed, AutoSaveTimer_Elapsed, Window_Closed) runs while GameSavesData.ToLPS() yields a null string — effectively a null/degenerate save data model.","commonSituations":"Autosave timer firing before the game data model was initialized; closing the window during early startup before GameSavesData is populated; corrupted/missing save data loaded as null.","solutions":["Ensure GameSavesData is initialized before Save/autosave can run (guard AutoSaveTimer start until data load completes).","Verify ToLPS()/ToString() never returns null (return empty LPS instead).","Skip the save when GameSavesData is null and log instead of throwing, so window close isn't blocked.","Repair or delete the corrupt save that produced a null model, then let the game recreate it."],"exampleFix":"// before\nvar savesdata = saveslps.ToString();\nif (savesdata == null)\n    throw new Exception(\"Save data is null\");\n// after\nif (GameSavesData == null) return; // nothing to save yet\nvar savesdata = saveslps?.ToString() ?? string.Empty;","handlingStrategy":"try-catch","validationCode":"if (GameSavesData == null) { /* skip save */ }","typeGuard":"bool CanSave() => GameSavesData != null && GameSavesData.ToLPS() != null;","tryCatchPattern":"try { Save(); } catch (Exception ex) when (ex.Message == \"Save data is null\") { Log.Warn(\"save skipped: no game data loaded yet\"); }","preventionTips":["Start the autosave timer only after game data is fully loaded","Initialize GameSavesData with an empty model instead of null","Never throw from Window_Closed handlers; log and degrade gracefully"],"tags":["save-data","null-reference","autosave"],"backgroundTag":"null-argument","analyzedSha":"ffb9cc2a856244a0f91aa5ecf10d097bcdd4954f","analyzedAt":"2026-09-15T21:21:10.398Z","contentChangedAt":"2026-09-15T21:21:10.398Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}