{"record":{"id":"5124d0a30e4593c8","repo":"ppy/osu","slug":"beat-length-cannot-be-nan-in-a-timing-control-poin","errorCode":null,"errorMessage":"Beat length cannot be NaN in a timing control point","messagePattern":"Beat length cannot be NaN in a timing control point","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs","lineNumber":533,"sourceCode":"\r\n            bool kiaiMode = false;\r\n            bool omitFirstBarSignature = false;\r\n\r\n            if (split.Length >= 8)\r\n            {\r\n                LegacyEffectFlags effectFlags = (LegacyEffectFlags)Parsing.ParseInt(split[7]);\r\n                kiaiMode = effectFlags.HasFlag(LegacyEffectFlags.Kiai);\r\n                omitFirstBarSignature = effectFlags.HasFlag(LegacyEffectFlags.OmitFirstBarLine);\r\n            }\r\n\r\n            string stringSampleSet = sampleSet.ToString().ToLowerInvariant();\r\n            if (stringSampleSet == @\"none\")\r\n                stringSampleSet = HitSampleInfo.BANK_NORMAL;\r\n\r\n            if (timingChange)\r\n            {\r\n                if (double.IsNaN(beatLength))\r\n                    throw new InvalidDataException(\"Beat length cannot be NaN in a timing control point\");\r\n\r\n                var controlPoint = CreateTimingControlPoint();\r\n\r\n                controlPoint.BeatLength = beatLength;\r\n                controlPoint.TimeSignature = timeSignature;\r\n                controlPoint.OmitFirstBarLine = omitFirstBarSignature;\r\n\r\n                addControlPoint(time, controlPoint, true);\r\n            }\r\n\r\n            int onlineRulesetID = beatmap.BeatmapInfo.Ruleset.OnlineID;\r\n\r\n            addControlPoint(time, new DifficultyControlPoint\r\n            {\r\n                GenerateTicks = !double.IsNaN(beatLength),\r\n                SliderVelocity = speedMultiplier,\r\n            }, timingChange);\r\n\r","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs#L515-L551","documentation":"Thrown by LegacyBeatmapDecoder when parsing a timing control point (TimingChange=1) whose beatLength field is NaN. The decoder explicitly rejects NaN timing points because they would corrupt the beatmap's timing grid. The value becomes NaN when the .osu file literally contains 'NaN' in the beatLength field, since double.Parse('NaN', InvariantCulture) successfully parses to double.NaN.","triggerScenarios":"Decoding a .osu file whose [TimingPoints] section contains a timing point (red/uninherited) with 'NaN' as the beatLength value — e.g. a line like '1000,NaN,4,1,0,100,1,0'. The timingChange flag must be true (first value after time is a positive beatLength, not an inherited multiplier).","commonSituations":"A beatmap produced by a buggy editor that wrote 'NaN' instead of a numeric BPM value; manual editing of a .osu file where a timing point value was deleted or replaced with text; a corrupt beatmap where the beatLength field is garbled.","solutions":["Open the .osu file in a text editor, find the [TimingPoints] section, and locate the offending line (the one with 'NaN' in the beatLength position).","Replace 'NaN' with a valid positive millisecond value (e.g. 60000/BPM — for 120 BPM use 500).","Re-export or re-download the beatmap if the corruption is widespread.","If producing .osu files programmatically, ensure beatLength is always a valid finite double before writing."],"exampleFix":"// before (.osu file [TimingPoints] section):\n// 1000,NaN,4,1,0,100,1,0\n\n// after:\n// 1000,500,4,1,0,100,1,0","handlingStrategy":"validation","validationCode":"// Validate beatLength before adding the timing point\nif (timingChange && double.IsNaN(beatLength))\n    throw new InvalidDataException($\"Timing point at {time}ms has NaN beatLength — fix the .osu file\");","typeGuard":null,"tryCatchPattern":"try\n{\n    var beatmap = decoder.Decode(stream);\n}\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"Beat length cannot be NaN\"))\n{\n    Logger.Log(\"Beatmap has a NaN timing point — file is corrupt\", LoggingTarget.Database);\n}","preventionTips":["If generating .osu files programmatically, ensure beatLength is always finite before writing.","Validate .osu timing point lines for 'NaN' before decoding.","Re-download corrupt beatmaps rather than attempting to force-decode them."],"tags":["beatmap-decoding","timing-points","nan","data-corruption"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}