XINCGer/Unity3DTraining · error · InvalidProtocolBufferException
Expected string value for Duration
Error message
Expected string value for Duration
What it means
MergeDuration requires the Duration well-known type to appear in JSON as a string (e.g. "3.5s"). If the JSON token for a google.protobuf.Duration field is not a string value (number, object, bool, null), the parser throws 'Expected string value for Duration'.
Solutions
- Encode the Duration as a string with an 's' suffix: "5s", "3.000000001s".
- Fix the producing side to follow the canonical protobuf JSON mapping for Duration.
- Catch InvalidProtocolBufferException and convert numeric inputs to the string form before parsing.
- If you control the schema, consider using int64 seconds fields instead of Duration when interop matters.
Example fix
// before
string json = "{\"duration\": 5}";
// after
string json = "{\"duration\": \"5s\"}"; Defensive patterns
Strategy: type-guard
Validate before calling
bool IsDurationStringToken(object token) => token is string; // caller-side: ensure the JSON field value is a string before parsing
Type guard
bool IsJsonString(object v) => v is string s && s != null; // or for JSON: if (field.Value.Type != JTokenType.String) reject;
Try / catch
try { var d = JsonParser.Default.Parse<Duration>(json); }
catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Expected string value for Duration"))
{ log.Warn("Duration field must be a string like \"5s\""); throw; } Prevention
- Always serialize Duration as "<seconds>s" string per the protobuf JSON mapping
- Never map Duration to a raw number or nested object
- Document the canonical form for API consumers
- Add schema validation that Duration fields are strings
When it happens
Trigger: Parsing JSON where a Duration field is given as a number ({"duration": 5}), an object ({"duration": {"seconds": 5}}), or null instead of the canonical string form ({"duration": "5s"}) via JsonParser.Parse<T>.
Common situations: JSON hand-written by developers assuming seconds-as-number; JSON from other serializers that map Duration to a numeric or struct; clients not following the protobuf JSON mapping spec.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Expected an object
- Unsupported JSON token type
- Unsupported conversion from JSON number for field type
- Invalid Duration value
- Expected string value for FieldMask
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/e6550db94230a48f.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs:863
if (timestamp.Seconds < Timestamp.UnixSecondsAtBclMinValue || timestamp.Seconds > Timestamp.UnixSecondsAtBclMaxValue)
{
throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue);
}
}
message.Descriptor.Fields[Timestamp.SecondsFieldNumber].Accessor.SetValue(message, timestamp.Seconds);
message.Descriptor.Fields[Timestamp.NanosFieldNumber].Accessor.SetValue(message, timestamp.Nanos);
}
catch (FormatException)
{
throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue);
}
}
private static void MergeDuration(IMessage message, JsonToken token)
{
if (token.Type != JsonToken.TokenType.StringValue)
{
throw new InvalidProtocolBufferException("Expected string value for Duration");
}
var match = DurationRegex.Match(token.StringValue);
if (!match.Success)
{
throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue);
}
var sign = match.Groups["sign"].Value;
var secondsText = match.Groups["int"].Value;
// Prohibit leading insignficant zeroes
if (secondsText[0] == '0' && secondsText.Length > 1)
{
throw new InvalidProtocolBufferException("Invalid Duration value: " + token.StringValue);
}
var subseconds = match.Groups["subseconds"].Value;
var multiplier = sign == "-" ? -1 : 1;
try
{View on GitHub (pinned to 016f98412e)