{"record":{"id":"b98dffa75f2e884a","repo":"XINCGer/Unity3DTraining","slug":"skiplastfield-called-on-an-end-group-tag-indicati","errorCode":null,"errorMessage":"SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing","messagePattern":"SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing","errorType":"exception","errorClass":"InvalidProtocolBufferException","httpStatus":null,"severity":"error","filePath":"NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/CodedInputStream.cs","lineNumber":408,"sourceCode":"        /// If a caller wishes to skip a group, they should skip the whole group, by calling this method after reading the\n        /// start-group tag. This behavior allows callers to call this method on any field they don't understand, correctly\n        /// resulting in an error if an end-group tag has not been paired with an earlier start-group tag.\n        /// </remarks>\n        /// <exception cref=\"InvalidProtocolBufferException\">The last tag was an end-group tag</exception>\n        /// <exception cref=\"InvalidOperationException\">The last read operation read to the end of the logical stream</exception>\n        public void SkipLastField()\n        {\n            if (lastTag == 0)\n            {\n                throw new InvalidOperationException(\"SkipLastField cannot be called at the end of a stream\");\n            }\n            switch (WireFormat.GetTagWireType(lastTag))\n            {\n                case WireFormat.WireType.StartGroup:\n                    SkipGroup(lastTag);\n                    break;\n                case WireFormat.WireType.EndGroup:\n                    throw new InvalidProtocolBufferException(\"SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing\");\n                case WireFormat.WireType.Fixed32:\n                    ReadFixed32();\n                    break;\n                case WireFormat.WireType.Fixed64:\n                    ReadFixed64();\n                    break;\n                case WireFormat.WireType.LengthDelimited:\n                    var length = ReadLength();\n                    SkipRawBytes(length);\n                    break;\n                case WireFormat.WireType.Varint:\n                    ReadRawVarint32();\n                    break;\n            }\n        }\n\n        private void SkipGroup(uint startGroupTag)\n        {","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/XINCGer/Unity3DTraining/blob/016f98412ea5e11756b286736f479b66ab6216d5/NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/CodedInputStream.cs#L390-L426","documentation":"When the pending lastTag has wire type EndGroup, SkipLastField() throws InvalidProtocolBufferException: an end-group tag means the matching start-group was closed (or never opened), so there is no field left to skip. This indicates malformed or desynchronized protobuf wire data.","triggerScenarios":"ReadTag() returned an end-group tag and the caller called SkipLastField() instead of treating it as the group terminator; parsing a stream whose group nesting is corrupted, or concatenating messages where a group end tag bleeds into the next parse session.","commonSituations":"Reusing a CodedInputStream across message boundaries in a multi-message stream (framing mismatch); hand-written parsers that don't break out of the loop on EndGroup wire type; truncated/corrupt network payloads.","solutions":["In the tag loop, check for WireFormat.WireType.EndGroup and break/return instead of calling SkipLastField().","Create a fresh CodedInputStream per delimited message; never continue parsing past an end-group tag.","Verify the framing code (length prefixes vs groups) matches how the sender serialized the data.","Catch InvalidProtocolBufferException and reject/log the payload as corrupt rather than resynchronizing."],"exampleFix":"// before\nswitch (WireFormat.GetTagWireType(tag))\n{\n    default: input.SkipLastField(); break; // EndGroup falls into default\n}\n// after\nvar wireType = WireFormat.GetTagWireType(tag);\nif (wireType == WireFormat.WireType.EndGroup) return; // group closed\nif (wireType != WireFormat.WireType.StartGroup) input.SkipLastField();","handlingStrategy":"try-catch","validationCode":"if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup) return; // do not skip","typeGuard":"bool IsEndGroupTag(int tag) => WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup;","tryCatchPattern":"try { input.SkipLastField(); } catch (InvalidProtocolBufferException ex) { logger.LogError(ex, \"Malformed wire data: stray end-group tag\"); discardCurrentMessage(); }","preventionTips":["Break out of the parse loop when the wire type is EndGroup.","Use one CodedInputStream per delimited message; do not parse across message boundaries.","Match framing to serialization: length-prefixed senders need length-prefixed readers."],"tags":["protobuf","corrupt-data","parsing"],"backgroundTag":"protobuf-unmarshal-failed","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"}