XINCGer/Unity3DTraining · error · InvalidProtocolBufferException

Mismatched end-group tag. Started with field

Error message

Mismatched end-group tag. Started with field 

What it means

While skipping a group, SkipGroup reads tags until it finds the end-group tag; if the end-group tag's field number differs from the start-group tag's field number, the wire data is malformed and InvalidProtocolBufferException('Mismatched end-group tag...') is thrown. Groups (SGROUP/EGROUP) are legacy protobuf wire types where start and end must share a field number.

Solutions

  1. Treat the payload as corrupt: catch InvalidProtocolBufferException, log the bytes, and drop or re-request the message.
  2. Verify sender and receiver share the same .proto schema, especially any legacy group declarations.
  3. Replace deprecated groups with nested messages in the schema if you control it.
  4. Re-check framing logic so each parse starts exactly at a message boundary.

Example fix

// before
input.SkipField(tag); // continues past mismatched group, corrupting state
// after
try { input.SkipField(tag); }
catch (InvalidProtocolBufferException ex)
{
    logger.LogError(ex, "Corrupt protobuf payload, dropping");
    return null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Framing.IsAtMessageBoundary(stream)) await RefillBufferAsync(); // ensure aligned reads

Type guard

null

Try / catch

try { parser.ParseFrom(stream); } catch (InvalidProtocolBufferException ex) when (ex.Message.StartsWith("Mismatched end-group")) { logger.LogError(ex, "Corrupt group nesting; dropping payload of {N} bytes", byteCount); metrics.Increment("protobuf_corrupt"); return null; }

Prevention

When it happens

Trigger: Parsing bytes where an end-group tag for a different field number appears — due to corrupted data, desynchronized framing, mixing fields written by incompatible schemas, or manually crafted byte arrays.

Common situations: Legacy wire format data (proto2 groups) parsed with mismatched message definitions; byte offsets slipping after a partial read so a group-end tag is interpreted at the wrong position; concatenating serialized payloads incorrectly.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/CodedInputStream.cs:454

            {
                tag = ReadTag();
                if (tag == 0)
                {
                    throw InvalidProtocolBufferException.TruncatedMessage();
                }
                // Can't call SkipLastField for this case- that would throw.
                if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup)
                {
                    break;
                }
                // This recursion will allow us to handle nested groups.
                SkipLastField();
            }
            int startField = WireFormat.GetTagFieldNumber(startGroupTag);
            int endField = WireFormat.GetTagFieldNumber(tag);
            if (startField != endField)
            {
                throw new InvalidProtocolBufferException("Mismatched end-group tag. Started with field " + startField + "; ended with field " + endField);
            }
            recursionDepth--;
        }

        /// <summary>
        /// Reads a double field from the stream.
        /// </summary>
        public double ReadDouble()
        {
            return BitConverter.Int64BitsToDouble((long)ReadRawLittleEndian64());
        }

        /// <summary>
        /// Reads a float field from the stream.
        /// </summary>
        public float ReadFloat()
        {
            if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)

View on GitHub (pinned to 016f98412e)