{"record":{"id":"69181d92cfa2a6e2","repo":"XINCGer/Unity3DTraining","slug":"invalid-field-mask-text","errorCode":null,"errorMessage":"Invalid field mask: {text}","messagePattern":"Invalid field mask: (.+?)","errorType":"exception","errorClass":"InvalidProtocolBufferException","httpStatus":null,"severity":"error","filePath":"NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs","lineNumber":959,"sourceCode":"                    if (wasNotUnderscore &&               //            case 1 out\n                        (wasNotCap ||                     // case 2 in, case 3 out\n                         (i + 1 < text.Length &&         //            case 3 out\n                          (text[i + 1] >= 'a' && text[i + 1] <= 'z')))) // ascii_islower(text[i + 1])\n                    {  // case 4 in\n                       // We add an underscore for case 2 and case 4.\n                        builder.Append('_');\n                    }\n                    // ascii_tolower, but we already know that c *is* an upper case ASCII character...\n                    builder.Append((char)(c + 'a' - 'A'));\n                    wasNotUnderscore = true;\n                    wasNotCap = false;\n                }\n                else\n                {\n                    builder.Append(c);\n                    if (c == '_')\n                    {\n                        throw new InvalidProtocolBufferException(\"Invalid field mask: \" + text);\n                    }\n                    wasNotUnderscore = true;\n                    wasNotCap = true;\n                }\n            }\n            return builder.ToString();\n        }\n        #endregion\n\n        /// <summary>\n        /// Settings controlling JSON parsing.\n        /// </summary>\n        public sealed class Settings\n        {\n            /// <summary>\n            /// Default settings, as used by <see cref=\"JsonParser.Default\"/>. This has the same default\n            /// recursion limit as <see cref=\"CodedInputStream\"/>, and an empty type registry.\n            /// </summary>","sourceCodeStart":941,"sourceCodeEnd":977,"githubUrl":"https://github.com/XINCGer/Unity3DTraining/blob/016f98412ea5e11756b286736f479b66ab6216d5/NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs#L941-L977","documentation":"Google.Protobuf's JsonParser throws this InvalidProtocolBufferException when converting a FieldMask from its JSON snake_case representation back to proto field paths. In a field mask, an underscore must always be followed by an ASCII letter that becomes the capitalized character of the camelCase proto field name. An underscore at the end of the string, or followed by anything other than a letter, cannot be mapped to a valid proto path, so the parser rejects it.","triggerScenarios":"Calling JsonParser.ParseJson (or any descriptor-driven FromJson) on JSON containing a FieldMask value with a trailing underscore (e.g. \"user._\"), a double underscore (\"user__id\"), or an underscore followed by a non-letter character. The throw site is in the field-mask path conversion loop at JsonParser.cs:959, reached whenever a field of type google.protobuf.FieldMask is parsed from JSON.","commonSituations":"Hand-written JSON where a field mask was typed with snake_case separators instead of valid camelCase-with-single-underscore encoding; code that built a field mask string by string concatenation leaving a trailing '_'; interoperating with a service that emits non-canonical field masks; migrating from a client library with laxer field-mask validation.","solutions":["Fix the JSON input: each '_' in a field mask must be immediately followed by a letter (the snake_case-to-camelCase encoding), e.g. \"user.profileName\", never \"user__id\" or \"user_.\"","Remove trailing underscores from field mask strings before sending them to ParseJson.","If generating field masks programmatically, use a canonical encoder (e.g. FieldMask.ToString / the WellKnownTypes FieldMask helpers) instead of hand-building strings.","If you control the producer, validate field masks against the target message's field names before serialization."],"exampleFix":"// before\nvar mask = json[\"updateMask\"].ToString(); // \"user__email\"\nvar parsed = JsonParser.Default.Parse<UpdateRequest>(json); // throws\n// after\nstring mask = json[\"updateMask\"].ToString().Replace(\"__\", \"_\").TrimEnd('_'); // \"user_email\"\nvar parsed = JsonParser.Default.Parse<UpdateRequest>(json);","handlingStrategy":"validation","validationCode":"static bool IsValidFieldMaskJson(string mask) =>\n    !string.IsNullOrEmpty(mask) && !mask.EndsWith(\"_\") && !mask.Contains(\"__\");\n// check each '_' is followed by [A-Za-z]\nif (!IsValidFieldMaskJson(mask)) throw new FormatException(\"Invalid field mask: \" + mask);","typeGuard":"static bool IsValidFieldMask(string mask)\n{\n    for (int i = 0; i < mask.Length; i++)\n        if (mask[i] == '_' && (i + 1 >= mask.Length || !char.IsAsciiLetter(mask[i + 1])))\n            return false;\n    return true;\n}","tryCatchPattern":"try\n{\n    var msg = JsonParser.Default.Parse<TRequest>(json);\n}\ncatch (InvalidProtocolBufferException ex) when (ex.Message.Contains(\"Invalid field mask\"))\n{\n    // log/repair the field mask string and retry\n}","preventionTips":["Always produce field masks via a canonical encoder, never by string concatenation","Trim trailing separators from user-supplied field mask input","Test field mask parsing round-trips (FieldMask -> JSON -> parser) in unit tests"],"tags":["protobuf","json-parsing","fieldmask","csharp"],"backgroundTag":"invalid-argument-format","analyzedSha":"016f98412ea5e11756b286736f479b66ab6216d5","analyzedAt":"2026-09-12T01:08:58.711Z","contentChangedAt":"2026-09-12T01:08:58.711Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}