XINCGer/Unity3DTraining · error · InvalidProtocolBufferException
Invalid numeric value
Error message
Invalid numeric value: {text} What it means
When a JSON string is parsed into a float/double field, ParseSingleStringValue checks whether the parsed value ended up as Infinity, -Infinity or NaN. The protobuf JSON mapping only permits the exact tokens 'Infinity', '-Infinity' and 'NaN' to denote these values; if the CLR parser produced a special value from some other text (a side effect of lenient parsing, e.g. case variants or whitespace handling), ValidateInfinityAndNan throws InvalidProtocolBufferException('Invalid numeric value: ' + text).
Solutions
- Use the exact tokens 'Infinity', '-Infinity' or 'NaN' as unquoted-per-spec JSON strings for special float values
- Normalize incoming tokens (trim, fix case, strip '+') before parsing
- Replace non-finite values with valid finite numbers or omit the field if special values are not required
- Validate float tokens against the three allowed special strings before calling the parser
Example fix
// before
parser.Parse<Point>("{\"x\": \"infinity\"}"); // wrong spelling
// after
parser.Parse<Point>("{\"x\": \"Infinity\"}"); Defensive patterns
Strategy: validation
Validate before calling
bool IsValidSpecialFloat(string text) =>
text == "Infinity" || text == "-Infinity" || text == "NaN" ||
double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var d) && !double.IsInfinity(d) && !double.IsNaN(d); Try / catch
try { return JsonParser.Default.Parse<T>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Invalid numeric value")) {
logger.LogWarning(ex, "Non-spec float token (Infinity/NaN spelling)");
return null;
} Prevention
- Only emit exactly 'Infinity', '-Infinity', 'NaN' for special floats
- Normalize case and strip '+'/whitespace from incoming float tokens
- Prefer omitting fields over encoding NaN/Infinity when consumers don't need them
When it happens
Trigger: JsonParser.Parse<T> on float/double fields with strings like 'infinity', '+Infinity', ' NaN ', or 'Inf' — tokens the CLR parser may accept leniently but that are not the spec-mandated spellings.
Common situations: JSON generated by non-.NET serializers using different infinity spellings; data round-tripped through logs or metrics systems that lowercase tokens; hand-written JSON with sign-prefixed Infinity.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Invalid field type
- Unable to format value of type
- Type registry has no descriptor for type name '
- Struct fields cannot have an empty key or a null value.
- Value message must contain a value for the oneof.
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/75f5ed68d876487b.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs:779
}
catch (OverflowException)
{
throw new InvalidProtocolBufferException("Value out of range: " + text);
}
}
/// <summary>
/// Checks that any infinite/NaN values originated from the correct text.
/// This corrects the lenient whitespace handling of double.Parse/float.Parse, as well as the
/// way that Mono parses out-of-range values as infinity.
/// </summary>
private static void ValidateInfinityAndNan(string text, bool isPositiveInfinity, bool isNegativeInfinity, bool isNaN)
{
if ((isPositiveInfinity && text != "Infinity") ||
(isNegativeInfinity && text != "-Infinity") ||
(isNaN && text != "NaN"))
{
throw new InvalidProtocolBufferException("Invalid numeric value: " + text);
}
}
private static void MergeTimestamp(IMessage message, JsonToken token)
{
if (token.Type != JsonToken.TokenType.StringValue)
{
throw new InvalidProtocolBufferException("Expected string value for Timestamp");
}
var match = TimestampRegex.Match(token.StringValue);
if (!match.Success)
{
throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue);
}
var dateTime = match.Groups["datetime"].Value;
var subseconds = match.Groups["subseconds"].Value;
var offset = match.Groups["offset"].Value;
View on GitHub (pinned to 016f98412e)