gravitational/teleport · error

proto: Passwordless: wiretype end group for non-group

Error message

proto: Passwordless: wiretype end group for non-group

What it means

This error is thrown by the gogo/protobuf-generated Unmarshal code for the Passwordless message in api/client/proto/authservice.pb.go. During binary protobuf decoding, if a field declares wire type 4 (end-group), which is only valid inside packed groups (deprecated), the decoder rejects it because Passwordless contains no group fields. It indicates the byte stream being decoded is not a valid encoding of the Passwordless message.

Source

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

		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: Passwordless: wiretype end group for non-group")
		}
		if fieldNum <= 0 {
			return fmt.Errorf("proto: Passwordless: illegal tag %d (wire type %d)", fieldNum, wire)
		}
		switch fieldNum {
		default:
			iNdEx = preIndex
			skippy, err := skipAuthservice(dAtA[iNdEx:])
			if err != nil {
				return err
			}
			if (skippy < 0) || (iNdEx+skippy) < 0 {
				return ErrInvalidLengthAuthservice
			}
			if (iNdEx + skippy) > l {
				return io.ErrUnexpectedEOF
			}
			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)

View on GitHub (pinned to 1283425b60)

Solutions

  1. Verify the bytes being unmarshaled were produced by Marshal of a Passwordless message and not truncated or offset
  2. Regenerate/rebuild both client and server from the same proto definitions to eliminate version skew
  3. Check that the transport is delivering raw protobuf, not base64/JSON-encoded data
  4. Log the raw payload (hex) and validate it with protoc --decode_raw to find the malformed field

Example fix

// before
var p proto.Passwordless
if err := p.Unmarshal(someOtherMessageBytes); err != nil { ... }
// after
var p proto.Passwordless
if err := p.Unmarshal(passwordlessBytes); err != nil { return trace.Wrap(err) }
Defensive patterns

Strategy: try-catch

Validate before calling

if len(payload) == 0 { return errors.New("empty payload") }
// optionally pre-check first wire byte: tag&0x7 != 4
if payload[0]&0x7 == 4 { return errors.New("invalid wire type (end group)") }

Type guard

func looksLikeProto(b []byte) bool {
  return len(b) > 0 && b[0] != 0 && b[0]&0x7 != 4 && b[0]&0x7 != 3
}

Try / catch

var p proto.Passwordless
if err := proto.Unmarshal(payload, &p); err != nil {
  return trace.BadParameter("invalid Passwordless payload: %v", err)
}

Prevention

When it happens

Trigger: Calling Unmarshal (directly or via gRPC) on bytes whose next wire tag has wireType==4 for the Passwordless message — i.e. corrupted, truncated-shifted, or non-protobuf bytes, or bytes of a different message type decoded as Passwordless.

Common situations: Version skew between client and server where one side changed field types; manually concatenating or slicing serialized messages; sending JSON/other bytes to a gRPC endpoint; reading a corrupted payload from a queue or file.

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 gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/a8795df8784913f1. Report an issue: GitHub.