grpc/grpc-go · error
received frame with size
Error message
received frame with size %v which is shorter than message type field size %v
What it means
Returned during ALTS record reading (conn.ReadOnReady) when a complete frame was received but the payload after the 4-byte length field is shorter than the 4-byte message-type field (msgTypeFieldSize). This means the frame is too small to even contain a message type, indicating a truncated or malformed frame.
Solutions
- Verify the peer runs a compliant ALTS implementation and matching gRPC version.
- Capture a packet trace to inspect the malformed frame.
- Treat as connection-fatal: the ALTS conn is now in an inconsistent state, so close it and let gRPC establish a new one.
- If reproducible only against one peer, focus the investigation on that peer's gRPC/ALTS build.
Defensive patterns
Strategy: try-catch
Try / catch
// Short frames mean the connection is corrupted; close it.
// Application code sees this as a transport error on the RPC; retry with backoff.
if err != nil && strings.Contains(err.Error(), "shorter than message type field size") {
_ = conn.Close() // discard corrupted ALTS connection
} Prevention
- Only connect ALTS endpoints to other legitimate ALTS endpoints on GCP.
- Investigate persistent short-frame errors with a packet capture.
- Do not attempt to recover a desynchronized ALTS connection; reconnect.
When it happens
Trigger: An ALTS-secured peer sends a frame whose declared length results in fewer than 4 bytes after the length header. Reached on every Read/ReadOnReady of an ALTS connection when a full frame is available.
Common situations: Memory corruption or bit-flips on the wire; a buggy or non-conformant ALTS peer; a man-in-the-middle injecting partial data; closing/tearing down the connection mid-frame in a way that produces a short final record.
Related errors
- received frame with incorrect message type
- received the frame length
- client-side RPC versions is not compatible with this…
- decode error
- expected 3 parts in token
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/f4b47a2af7096178.
Report an issue: GitHub.
Appendix: 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 0c51461d27)