gravitational/teleport · error

proto: CreatePrivilegeTokenRequest: wiretype end group for n

Error message

proto: CreatePrivilegeTokenRequest: wiretype end group for non-group

What it means

Wire type 4 (END_GROUP) can only appear as the terminator of an embedded group started with wire type 3 (START_GROUP). The generated Unmarshal for CreatePrivilegeTokenRequest hit an END_GROUP byte with no matching start, so it rejects the payload as structurally invalid. Groups are deprecated proto2 constructs that this schema does not use at all, so such bytes are always invalid here.

Source

Thrown at api/client/proto/authservice.pb.go:60418

		var wire uint64
		for shift := uint(0); ; shift += 7 {
			if shift >= 64 {
				return ErrIntOverflowAuthservice
			}
			if iNdEx >= l {
				return io.ErrUnexpectedEOF
			}
			b := dAtA[iNdEx]
			iNdEx++
			wire |= uint64(b&0x7F) << shift
			if b < 0x80 {
				break
			}
		}
		fieldNum := int32(wire >> 3)
		wireType := int(wire & 0x7)
		if wireType == 4 {
			return fmt.Errorf("proto: CreatePrivilegeTokenRequest: wiretype end group for non-group")
		}
		if fieldNum <= 0 {
			return fmt.Errorf("proto: CreatePrivilegeTokenRequest: illegal tag %d (wire type %d)", fieldNum, wire)
		}
		switch fieldNum {
		case 1:
			if wireType != 2 {
				return fmt.Errorf("proto: wrong wireType = %d for field ExistingMFAResponse", wireType)
			}
			var msglen int
			for shift := uint(0); ; shift += 7 {
				if shift >= 64 {
					return ErrIntOverflowAuthservice
				}
				if iNdEx >= l {
					return io.ErrUnexpectedEOF
				}
				b := dAtA[iNdEx]

View on GitHub (pinned to 1283425b60)

Solutions

  1. Unmarshal from a message boundary — make sure you pass exactly one marshaled message, not a slice of a stream
  2. Confirm both peers use matching api/client/proto generated code
  3. Check transport integrity (TLS, framing) for truncation/corruption
  4. Regenerate the payload with proto.Marshal instead of reusing hand-built bytes

Example fix

// before: slicing a stream at a wrong offset
err := proto.Unmarshal(streamBuf[7:], req) // offset lands on a stray byte
// after: use a length-delimited framing reader
var l uint64
buf = binary.Uvarint... // read length prefix, then Unmarshal exactly l bytes
Defensive patterns

Strategy: try-catch

Validate before calling

func startsWithValidTag(b []byte) bool {
    if len(b) == 0 { return false }
    tag, n := binary.Uvarint(b)
    return n > 0 && tag>>3 >= 1 && tag&0x7 != 4
}

Type guard

func isMalformedWireData(err error) bool {
    return err != nil && (strings.Contains(err.Error(), "end group for non-group") || strings.Contains(err.Error(), "illegal tag"))
}

Try / catch

if err := proto.Unmarshal(buf, req); err != nil {
    if isMalformedWireData(err) {
        return trace.BadParameter("payload is not a valid CreatePrivilegeTokenRequest; check framing")
    }
    return trace.Wrap(err)
}

Prevention

When it happens

Trigger: Bytes passed to CreatePrivilegeTokenRequest Unmarshal contain a tag whose low 3 bits equal 4 — i.e. a stray 0x??4 tag byte — due to corruption, offset desync, or an encoder emitting group markers.

Common situations: A byte-stream desync (parsing in the middle of a larger buffer instead of at a message boundary); corruption over a broken transport; a custom/fuzz encoder emitting proto2 group syntax; decoding the wrong message type's bytes.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/b29c8e10b4a16178. Report an issue: GitHub.