grpc/grpc-go · error
received frame with size %v which is shorter than message ty
Error message
received frame with size %v which is shorter than message type field size %v
What it means
In conn.ReadOnReady (record.go:267-269), after a complete frame is parsed, the payload after the 4-byte length header must still contain the 4-byte message-type field (msgTypeFieldSize). If the declared frame length is so small that less than 4 bytes of payload remain, the frame is malformed and the connection errors. This is a defensive check on ALTS record framing.
Source
Thrown at credentials/alts/internal/conn/record.go:269
}
p.protectedHandle = newBuf
protected = (*newBuf)[:nRead]
} else {
nRead, err := p.Conn.Read(protected[len(protected):cap(protected)])
if err != nil {
return nil, 0, err
}
protected = protected[:len(protected)+nRead]
}
framedMsg, p.nextFrame, err = ParseFramedMsg(protected, altsRecordLengthLimit)
if err != nil {
return nil, 0, err
}
}
// Now we have a complete frame, decrypted it.
msg := framedMsg[MsgLenFieldSize:]
if len(msg) < msgTypeFieldSize {
return nil, 0, fmt.Errorf("received frame with size %v which is shorter than message type field size %v", len(msg), msgTypeFieldSize)
}
msgType := binary.LittleEndian.Uint32(msg[:msgTypeFieldSize])
if msgType&0xff != altsRecordMsgType {
return nil, 0, fmt.Errorf("received frame with incorrect message type %v, expected lower byte %v",
msgType, altsRecordMsgType)
}
ciphertext := msg[msgTypeFieldSize:]
// Decrypt directly into the buffer, avoiding a copy from p.buf if
// possible.
if bufSize >= len(ciphertext) {
allocatedBuf := pool.Get(bufSize)
dec, err := p.crypto.Decrypt((*allocatedBuf)[:0], ciphertext)
if err != nil {
pool.Put(allocatedBuf)
return nil, 0, err
}
p.dropProtectedIfEmtpy()View on GitHub (pinned to 03255a9237)
Solutions
- Ensure the peer implements ALTS record framing correctly (length covers >= msgTypeFieldSize).
- Treat as connection-fatal: close the ALTS connection and reconnect.
- In tests, build frames with at least MsgLenFieldSize+msgTypeFieldSize bytes.
Example fix
// before: test frame declares length 2 binary.LittleEndian.PutUint32(buf, 2) // after: declare length >= 4 (msgTypeFieldSize) binary.LittleEndian.PutUint32(buf, 4)
Defensive patterns
Strategy: try-catch
Try / catch
n, err := altsConn.Read(buf)
if err != nil {
if strings.Contains(err.Error(), "shorter than message type field size") {
log.Printf("malformed ALTS frame; closing connection")
altsConn.Close()
}
return n, err
} Prevention
- Treat malformed-frame errors as connection-fatal.
- In tests, always include the msgTypeFieldSize (4 bytes) of payload.
- Fuzz-test peers to confirm they reject truncated frames.
When it happens
Trigger: A peer (or corrupted stream) sends an ALTS record whose length header indicates a payload smaller than the 4-byte message-type sub-field — e.g. a frame length of 0–3. Encountered during conn.Read/ReadOnReady.
Common situations: A non-conformant or malicious peer; stream corruption; a fuzz test feeding truncated frames; an ALTS implementation bug producing zero-length records.
Related errors
- received the frame length %d larger than the limit %d
- received frame with incorrect message type %v, expected lowe
- no error details for status with code OK
- duplicated name
- wrr: errorUtilizationPenalty must be non-negative
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/f4b47a2af7096178.
Report an issue: GitHub.