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
- Unmarshal from a message boundary — make sure you pass exactly one marshaled message, not a slice of a stream
- Confirm both peers use matching api/client/proto generated code
- Check transport integrity (TLS, framing) for truncation/corruption
- 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
- Unmarshal only from verified message boundaries with length-prefix framing
- Verify transport integrity (TLS, no frame-rewriting proxies)
- Replace hand-built byte fixtures with proto.Marshal output
- Reject zero-padded/truncated buffers before decoding
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
- proto: CreatePrivilegeTokenRequest: illegal tag %d (wire typ
- proto: CreateRegisterChallengeRequest: wiretype end group fo
- proto: CreateRegisterChallengeRequest: illegal tag %d (wire
- proto: Passwordless: wiretype end group for non-group
- proto: Passwordless: illegal tag %d (wire type %d)
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/b29c8e10b4a16178.
Report an issue: GitHub.