ppy/osu · error · FormatException
Not a number
Error message
Not a number
What it means
Thrown by Parsing.ParseFloat when the parsed value is NaN and the allowNaN parameter is false (the default). This fires after the range checks pass, because NaN comparisons always return false. double.Parse/float.Parse will produce NaN if the input string is literally 'NaN'.
Source
Thrown at osu.Game/Beatmaps/Formats/Parsing.cs:25
namespace osu.Game.Beatmaps.Formats
{
/// <summary>
/// Helper methods to parse from string to number and perform very basic validation.
/// </summary>
public static class Parsing
{
public const int MAX_COORDINATE_VALUE = 131072;
public const double MAX_PARSE_VALUE = int.MaxValue;
public static float ParseFloat(string input, float parseLimit = (float)MAX_PARSE_VALUE, bool allowNaN = false)
{
float output = float.Parse(input, CultureInfo.InvariantCulture);
if (output < -parseLimit) throw new OverflowException("Value is too low");
if (output > parseLimit) throw new OverflowException("Value is too high");
if (!allowNaN && float.IsNaN(output)) throw new FormatException("Not a number");
return output;
}
public static double ParseDouble(string input, double parseLimit = MAX_PARSE_VALUE, bool allowNaN = false)
{
double output = double.Parse(input, CultureInfo.InvariantCulture);
if (output < -parseLimit) throw new OverflowException("Value is too low");
if (output > parseLimit) throw new OverflowException("Value is too high");
if (!allowNaN && double.IsNaN(output)) throw new FormatException("Not a number");
return output;
}
public static int ParseInt(string input, int parseLimit = (int)MAX_PARSE_VALUE)
{
View on GitHub (pinned to d9c73e12ad)
Solutions
- Locate the field containing 'NaN' in the .osu/.osb file and replace it with a valid finite number.
- If calling ParseFloat directly and NaN is a legitimate sentinel value, pass allowNaN: true.
- Sanitize input strings before parsing — replace 'NaN' with '0' or reject the input.
Example fix
// before float value = Parsing.ParseFloat(input); // throws if input is "NaN" // after (if NaN is legitimate): float value = Parsing.ParseFloat(input, allowNaN: true); // after (if NaN is invalid, fix the data): // .osu file: replace 'NaN' with a real number like '0'
Defensive patterns
Strategy: validation
Validate before calling
// Check for NaN before parsing
if (float.TryParse(input, CultureInfo.InvariantCulture, out float test) && float.IsNaN(test))
throw new FormatException($"Input '{input}' is NaN and NaN is not allowed here");
float value = Parsing.ParseFloat(input); Try / catch
try
{
float value = Parsing.ParseFloat(input);
}
catch (FormatException ex) when (ex.Message == "Not a number")
{
Logger.Log($"Field value '{input}' is NaN — fix the .osu file", LoggingTarget.Database);
} Prevention
- If NaN is a legitimate sentinel value, pass allowNaN: true to ParseFloat.
- Sanitize input strings to replace 'NaN' with a valid default before parsing.
- When generating .osu files, never write float.NaN.ToString() — always write finite values.
When it happens
Trigger: Calling Parsing.ParseFloat(input) where input is the string 'NaN' (case-insensitive, since float.Parse accepts it) and allowNaN defaults to false. This commonly occurs when a beatmap field contains the literal text 'NaN' where a number is expected.
Common situations: A .osu file where a numeric field (coordinate, timing value, difficulty setting) was set to 'NaN' by a buggy editor or manual edit; a computation that wrote float.NaN.ToString() into the file; corruption during file transfer.
Related errors
- Value is too low
- Beat length cannot be NaN in a timing control point
- Color specified in incorrect format (should be R,G,B or R,G,
- Ruleset is not available locally.
- Color must be specified with 8-bit integer components
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/f8434ebe171004fa.
Report an issue: GitHub.