gravitational/teleport · error

proto: CreateRegisterChallengeRequest: wiretype end group fo

Error message

proto: CreateRegisterChallengeRequest: wiretype end group for non-group

What it means

The generated Unmarshal for CreateRegisterChallengeRequest encountered an END_GROUP wire type (4) with no preceding START_GROUP. Since this message schema contains no groups, such bytes are structurally invalid and decoding aborts. This is generated-code protection against corrupt or mismatched wire data.

Source

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

		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: CreateRegisterChallengeRequest: wiretype end group for non-group")
		}
		if fieldNum <= 0 {
			return fmt.Errorf("proto: CreateRegisterChallengeRequest: illegal tag %d (wire type %d)", fieldNum, wire)
		}
		switch fieldNum {
		case 1:
			if wireType != 2 {
				return fmt.Errorf("proto: wrong wireType = %d for field TokenID", wireType)
			}
			var stringLen uint64
			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. Ensure Unmarshal receives exactly one complete message starting at byte 0 of the buffer
  2. Use proper gRPC framing instead of manual stream slicing
  3. Verify both endpoints run matching generated proto code
  4. Re-produce the payload with proto.Marshal to replace suspect bytes

Example fix

// before: wrong offset into a framed stream
err := proto.Unmarshal(buf[3:], req)
// after: frame with length prefixes
msgLen, n := binary.Uvarint(hdr)
err = proto.Unmarshal(buf[n:n+int(msgLen)], req)
Defensive patterns

Strategy: validation

Validate before calling

func alignedMessageBoundary(b []byte) error {
    if len(b) == 0 { return errors.New("empty payload") }
    tag, n := binary.Uvarint(b)
    if n <= 0 { return errors.New("cannot decode leading tag: not at a message boundary") }
    if tag&0x7 == 4 { return errors.New("payload starts with END_GROUP; misaligned") }
    return nil
}

Type guard

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

Try / catch

if err := proto.Unmarshal(buf, req); err != nil {
    if isEndGroupError(err) {
        return trace.BadParameter("stream framing desync detected; reset connection")
    }
    return trace.Wrap(err)
}

Prevention

When it happens

Trigger: Passing bytes containing a stray wire-type-4 tag to CreateRegisterChallengeRequest Unmarshal — from stream desync, corrupted frames, or a nonstandard encoder emitting proto2 group markers.

Common situations: Reading a payload from the middle of a multiplexed stream; truncated/reassembled TCP frames; fuzz testing; decoding another message type's serialized bytes as this request.

Related errors


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