XINCGer/Unity3DTraining · error · InvalidOperationException
Invalid field mask to be converted to JSON
Error message
Invalid field mask to be converted to JSON: {firstInvalid} What it means
FieldMask.ToJson validates that every path in the mask is a valid lowercase snake_case field path (validating conversion). If any path contains characters invalid for JSON field-mask representation (e.g. CamelCase segments that would need camel-conversion but are invalid), it throws InvalidOperationException naming the first invalid path. Field masks in JSON must use camelCase, and the library requires paths it can validate before converting.
Solutions
- Convert paths to valid snake_case protobuf field names before adding them (FieldMask.Util.ToUpperCamelCase is for output; input must be lowercase snake_case)
- Use FieldMask.ForFieldNames or construct from reflection-derived protobuf field names rather than raw strings
- Fix the specific path named in the exception message
- If interop requires camelCase input, normalize with a snake_case converter before adding to Paths
Example fix
// before
var mask = new FieldMask();
mask.Paths.Add("DisplayName"); // invalid
var s = mask.ToDiagnosticString(); // throws
// after
var mask2 = new FieldMask();
mask2.Paths.Add("display_name");
var s2 = mask2.ToDiagnosticString(); // "displayName" Defensive patterns
Strategy: validation
Validate before calling
static bool IsValidFieldMaskPath(string p) => !string.IsNullOrEmpty(p) && p.All(c => char.IsLower(c) || char.IsDigit(c) || c == '_' || c == '.');
Type guard
static bool IsUsableFieldMask(FieldMask m) => m != null && m.Paths.Count > 0 && m.Paths.All(IsValidFieldMaskPath);
Try / catch
try { return mask.ToDiagnosticString(); } catch (InvalidOperationException ex) { log.Warn(ex, "Invalid field mask"); return string.Join(",", mask.Paths); } Prevention
- Store protobuf field names (snake_case), not C# property names
- Derive paths from field descriptors instead of hard-coded strings
- Test masks against the JSON round-trip in unit tests
When it happens
Trigger: Calling ToDiagnosticString()/ToJson() on a FieldMask whose Paths contain entries like 'FooBar' or paths with invalid characters, so IsValidPath/validating conversion fails and firstInvalid holds the offending path.
Common situations: Building field masks from C# property names (PascalCase) instead of protobuf field names; hand-writing paths with typos; masks constructed programmatically from user input; mixing camelCase and snake_case when copying from JSON examples.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Non-normalized duration value
- Non-normalized timestamp value
- Did not write as much data as expected.
- Expected string value for FieldMask
- Invalid field mask
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/b9c786da530ac5c3.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs:78
{
var writer = new StringWriter();
var query = paths.Select<string, string>(JsonFormatter.ToJsonName);
JsonFormatter.WriteString(writer, string.Join(",", query.ToArray()));
return writer.ToString();
}
else
{
if (diagnosticOnly)
{
var writer = new StringWriter();
writer.Write("{ \"@warning\": \"Invalid FieldMask\", \"paths\": ");
JsonFormatter.Default.WriteList(writer, (IList)paths);
writer.Write(" }");
return writer.ToString();
}
else
{
throw new InvalidOperationException("Invalid field mask to be converted to JSON: " + firstInvalid);
}
}
}
/// <summary>
/// Checks whether the given path is valid for a field mask.
/// </summary>
/// <returns>true if the path is valid; false otherwise</returns>
private static bool ValidatePath(string input)
{
for (int i = 0; i < input.Length; i++)
{
char c = input[i];
if (c >= 'A' && c <= 'Z')
{
return false;
}
if (c == '_' && i < input.Length - 1)View on GitHub (pinned to 016f98412e)