{"record":{"id":"f9845fb68b07e423","repo":"ppy/osu","slug":"error-when-exporting-model-getdisplaystring-m","errorCode":null,"errorMessage":"Error when exporting {model.GetDisplayString()}: Multiple files specify filename of {file.Filename}","messagePattern":"Error when exporting (.+?): Multiple files specify filename of (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"osu.Game/Database/LegacyArchiveExporter.cs","lineNumber":58,"sourceCode":"        {\r\n            var zipWriterOptions = new ZipWriterOptions(CompressionType.Deflate)\r\n            {\r\n                ArchiveEncoding = UseFixedEncoding ? ZipArchiveReader.DEFAULT_ENCODING : new ArchiveEncoding { Default = Encoding.UTF8, Password = Encoding.UTF8 }\r\n            };\r\n\r\n            using (var writer = new ZipWriter(outputStream, zipWriterOptions))\r\n            {\r\n                int i = 0;\r\n                int fileCount = model.Files.Count();\r\n                bool anyFileMissing = false;\r\n                HashSet<string> filesWritten = [];\r\n\r\n                foreach (var file in model.Files)\r\n                {\r\n                    cancellationToken.ThrowIfCancellationRequested();\r\n\r\n                    if (filesWritten.Contains(file.Filename))\r\n                        throw new InvalidOperationException($\"Error when exporting {model.GetDisplayString()}: Multiple files specify filename of {file.Filename}\");\r\n\r\n                    using (var stream = GetFileContents(model, file))\r\n                    {\r\n                        if (stream == null)\r\n                        {\r\n                            Logger.Log($\"File {file.Filename} is missing in local storage and will not be included in the export\", LoggingTarget.Database);\r\n                            anyFileMissing = true;\r\n                            continue;\r\n                        }\r\n\r\n                        writer.Write(file.Filename, stream);\r\n                        filesWritten.Add(file.Filename);\r\n                    }\r\n\r\n                    i++;\r\n\r\n                    if (notification != null)\r\n                    {\r","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/Database/LegacyArchiveExporter.cs#L40-L76","documentation":"Thrown by LegacyArchiveExporter during zip export when two files in the model's Files collection share the same Filename. The exporter tracks filenames in a HashSet and refuses to overwrite a duplicate entry inside the zip, which would silently lose data. This typically indicates a data integrity issue in the underlying model.","triggerScenarios":"Calling export on a model (e.g. BeatmapSetInfo or SkinInfo) whose Files collection contains two or more entries with an identical Filename string. The exporter encounters the second occurrence and aborts.","commonSituations":"A beatmap set with two BeatmapInfo entries whose computed paths point to the same filename (shouldn't happen normally but can result from a bug in filename generation or a corrupted realm database); a skin with duplicate file entries after a botched merge or import; a race condition where a file was added twice.","solutions":["Inspect the model's Files collection for duplicate Filenames before exporting.","Deduplicate the Files entries — keep one and remove or rename the others.","If the duplicates are in the realm database, use PerformWrite to fix the model before re-attempting export.","Investigate the root cause of the duplicate creation (import bug, concurrent writes)."],"exampleFix":"// before\nexporter.Export(model); // throws if model.Files has duplicate filenames\n\n// after\nvar duplicates = model.Files\n    .GroupBy(f => f.Filename)\n    .Where(g => g.Count() > 1)\n    .ToList();\nif (duplicates.Any())\n    throw new InvalidOperationException($\"Cannot export: duplicate filenames: {string.Join(\", \", duplicates.Select(g => g.Key))}\");\nexporter.Export(model);","handlingStrategy":"validation","validationCode":"// Check for duplicate filenames before exporting\nvar duplicates = model.Files\n    .GroupBy(f => f.Filename)\n    .Where(g => g.Count() > 1)\n    .Select(g => g.Key)\n    .ToList();\nif (duplicates.Any())\n    throw new InvalidOperationException($\"Duplicate filenames prevent export: {string.Join(\", \", duplicates)}\");","typeGuard":null,"tryCatchPattern":"try\n{\n    exporter.Export(model);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Multiple files specify filename\"))\n{\n    Logger.Log($\"Export aborted — duplicate files: {ex.Message}\", LoggingTarget.Database);\n    // deduplicate or prompt user\n}","preventionTips":["Enforce filename uniqueness when adding files to a model's Files collection.","Run a dedup check before export operations.","Investigate and fix root causes of duplicate file entries (import bugs, concurrent writes)."],"tags":["archive-export","zip","duplicate-files","data-integrity"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}