{"record":{"id":"4365c5afc3ded6a3","repo":"ppy/osu","slug":"only-beatmaps-in-the-osu-taiko-catch-or-mania-r","errorCode":null,"errorMessage":"Only beatmaps in the osu, taiko, catch, or mania rulesets can be encoded to the legacy beatmap format.","messagePattern":"Only beatmaps in the osu, taiko, catch, or mania rulesets can be encoded to the legacy beatmap format\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs","lineNumber":53,"sourceCode":"        /// </summary>\r\n        /// <param name=\"beatmap\">The beatmap to encode.</param>\r\n        /// <param name=\"skin\">The beatmap's skin, used for encoding combo colours.</param>\r\n        /// <param name=\"storyboard\">\r\n        /// The combined storyboard, loaded from both the <c>.osu</c> and the <c>.osz</c>.\r\n        /// Only elements from the <c>.osu</c> (marked via <see cref=\"StoryboardElementSource.Beatmap\"/>) will be encoded to the beatmap.\r\n        /// </param>\r\n        public LegacyBeatmapEncoder(IBeatmap beatmap, ISkin? skin, Storyboard? storyboard)\r\n        {\r\n            this.beatmap = beatmap;\r\n            this.skin = skin;\r\n\r\n            if (storyboard != null)\r\n                storyboardEncoder = new LegacyStoryboardEncoder(storyboard);\r\n\r\n            onlineRulesetID = beatmap.BeatmapInfo.Ruleset.OnlineID;\r\n\r\n            if (onlineRulesetID < 0 || onlineRulesetID > 3)\r\n                throw new ArgumentException(\"Only beatmaps in the osu, taiko, catch, or mania rulesets can be encoded to the legacy beatmap format.\", nameof(beatmap));\r\n        }\r\n\r\n        public void Encode(TextWriter writer)\r\n        {\r\n            writer.WriteLine($\"osu file format v{FIRST_LAZER_VERSION}\");\r\n\r\n            writer.WriteLine();\r\n            handleGeneral(writer);\r\n\r\n            writer.WriteLine();\r\n            handleEditor(writer);\r\n\r\n            writer.WriteLine();\r\n            handleMetadata(writer);\r\n\r\n            writer.WriteLine();\r\n            handleDifficulty(writer);\r\n\r","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs#L35-L71","documentation":"Thrown by the LegacyBeatmapEncoder constructor when the beatmap's ruleset OnlineID is outside the range 0–3. Only the four legacy rulesets (osu=0, taiko=1, catch=2, mania=3) can be encoded to the .osu legacy format. Custom rulesets have OnlineID values outside this range (often negative) and their mechanics cannot be represented in the legacy format.","triggerScenarios":"Constructing `new LegacyBeatmapEncoder(beatmap, skin, storyboard)` where beatmap.BeatmapInfo.Ruleset.OnlineID is <0 or >3 — i.e. a custom/experimental ruleset beatmap (e.g. senton, rush, tau, etc.).","commonSituations":"Attempting to export/save a custom ruleset beatmap in legacy .osu format; programmatically creating a LegacyBeatmapEncoder for a beatmap whose ruleset isn't one of the four standard ones; a ruleset that reports OnlineID=-1 (unregistered) being passed to the encoder.","solutions":["Only use LegacyBeatmapEncoder for beatmaps in the osu, taiko, catch, or mania rulesets (OnlineID 0–3).","Before constructing the encoder, check beatmap.BeatmapInfo.Ruleset.OnlineID and skip/handle custom rulesets differently.","For custom rulesets, use a non-legacy encoding path or skip export entirely."],"exampleFix":"// before\nvar encoder = new LegacyBeatmapEncoder(beatmap, skin, storyboard); // throws for custom rulesets\n\n// after\nif (beatmap.BeatmapInfo.Ruleset.OnlineID < 0 || beatmap.BeatmapInfo.Ruleset.OnlineID > 3)\n    throw new NotSupportedException($\"Ruleset {beatmap.BeatmapInfo.Ruleset.Name} cannot be encoded to legacy format\");\nvar encoder = new LegacyBeatmapEncoder(beatmap, skin, storyboard);","handlingStrategy":"validation","validationCode":"// Check ruleset OnlineID before encoding\nint rulesetId = beatmap.BeatmapInfo.Ruleset.OnlineID;\nif (rulesetId < 0 || rulesetId > 3)\n    throw new NotSupportedException($\"Ruleset {rulesetId} cannot be encoded to legacy .osu format\");\nvar encoder = new LegacyBeatmapEncoder(beatmap, skin, storyboard);","typeGuard":"static bool CanEncodeToLegacy(IBeatmap beatmap)\n{\n    int id = beatmap.BeatmapInfo.Ruleset.OnlineID;\n    return id >= 0 && id <= 3;\n}","tryCatchPattern":null,"preventionTips":["Only encode beatmaps from the four standard rulesets (osu, taiko, catch, mania) to legacy format.","Check OnlineID range before constructing LegacyBeatmapEncoder.","Provide an alternative export path for custom rulesets (e.g. JSON or skip export)."],"tags":["beatmap-encoding","legacy-format","ruleset","unsupported-operation"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}