XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Value out of range

Error message

Value out of range: {text}

What it means

ParseNumericString catches OverflowException from the underlying type parser (e.g. int.Parse on a value beyond int.MaxValue) and rethrows it as InvalidProtocolBufferException('Value out of range: ' + text). This means the JSON number is grammatically valid but cannot fit the declared proto field type (e.g. 3000000000 for int32, or a double too large for a float field).

Solutions

  1. Change the proto field to a wider type (int64/uint64 or double) and regenerate the C# classes
  2. Clamp or validate the value client-side against the target type's MinValue/MaxValue before serializing/parsing
  3. For big values that must stay int32-typed per an existing schema, transmit them as strings (int64-as-string JSON mapping)
  4. Use unsigned types (uint32/uint64) if values only overflow because they were meant to be non-negative

Example fix

// before
// proto: int32 id = 1;  json: {"id": 3000000000} -> overflow
// after
// proto: int64 id = 1;  regenerate stubs, then:
var msg = JsonParser.Default.Parse<Message>("{\"id\": 3000000000}");
Defensive patterns

Strategy: validation

Validate before calling

bool FitsType(long v, string protoType) => protoType switch {
    "int32"  => v >= int.MinValue && v <= int.MaxValue,
    "uint32" => v >= 0 && v <= uint.MaxValue,
    "int64"  => true,
    _ => true
};
// check bounds before serializing into JSON

Try / catch

try { return JsonParser.Default.Parse<T>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Value out of range")) {
    logger.LogWarning(ex, "Numeric value exceeds field type range");
    return null;
}

Prevention

When it happens

Trigger: JsonParser.Parse<T> where a numeric field receives a value outside its type's range: >2^31-1 for int32, >2^63-1 for int64, magnitudes beyond float range for float fields, or negative values for unsigned-typed fields.

Common situations: Server using 64-bit IDs sent into an int32 field; timestamp-like millisecond values exceeding int32; language-agnostic producers assuming 'int' means 64-bit; float fields given double-precision extremes.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

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

            }
            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"))
            {
                throw new InvalidProtocolBufferException("Invalid numeric value: " + text);
            }
        }

View on GitHub (pinned to 016f98412e)