XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Invalid numeric value for type:

Error message

Invalid numeric value for type: 

What it means

After passing the grammar checks, ParseNumericString invokes the actual parser (int.Parse/long.Parse/double.Parse via delegate) with invariant culture. A FormatException means the text, while superficially numeric-looking, is not parseable as the target CLR type (e.g. embedded whitespace, multiple decimal points, trailing garbage). The library rethrows it as InvalidProtocolBufferException('Invalid numeric value for type: ' + text).

Solutions

  1. Validate/normalize the numeric string before embedding it in JSON (strip separators, use '.' as decimal point)
  2. Use CultureInfo.InvariantCulture when converting numbers to strings for JSON
  3. Parse the value yourself first (int.TryParse/InvariantCulture) and serialize the typed value, not the raw string
  4. Check which proto field type the token targets and match its expected textual form (integer vs decimal vs exponent)

Example fix

// before
string json = "{\"amount\": " + amount.ToString("N2") + "}"; // "1,234.50"
// after
string json = "{\"amount\": " + amount.ToString(CultureInfo.InvariantCulture) + "}"; // 1234.5
Defensive patterns

Strategy: validation

Validate before calling

bool IsCleanNumber(string text) =>
    double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out _);

Try / catch

try { return JsonParser.Default.Parse<T>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Invalid numeric value for type")) {
    logger.LogWarning(ex, "Non-parseable numeric token");
    return null;
}

Prevention

When it happens

Trigger: JsonParser.Parse<T> with numeric tokens like '1 000', '1.2.3', '0x1F', '1_000', or a double-formatted token for an int-typed field where the parser delegate expects an integer form.

Common situations: Numbers scraped from UIs with thousand separators or spaces; hex or underscore literals copied from source code; locale-formatted strings (comma decimal separator) leaking into JSON; template concatenation mistakes.

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


AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/9a6a3d648f2b756b. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs:760

                if (text[1] >= '0' && text[1] <= '9')
                {
                    throw new InvalidProtocolBufferException("Invalid numeric value: " + text);
                }
            }
            else if (text.StartsWith("-0") && text.Length > 2)
            {
                if (text[2] >= '0' && text[2] <= '9')
                {
                    throw new InvalidProtocolBufferException("Invalid numeric value: " + text);
                }
            }
            try
            {
                return parser(text, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture);
            }
            catch (FormatException)
            {
                throw new InvalidProtocolBufferException("Invalid numeric value for type: " + text);
            }
            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"))
            {

View on GitHub (pinned to 016f98412e)