grpc/grpc-go · error

received the frame length %d larger than the limit %d

Error message

received the frame length %d larger than the limit %d

What it means

ParseFramedMsg (common.go:54-62) reads the 4-byte little-endian frame length header from an ALTS record and rejects frames whose declared length exceeds maxLen. On the record path maxLen is altsRecordLengthLimit (1 MiB). This guards against memory-exhaustion / oversized-record attacks on the ALTS secure channel.

Source

Thrown at credentials/alts/internal/conn/common.go:62

	} else {
		head = make([]byte, total)
		copy(head, in)
	}
	tail = head[len(in):]
	return head, tail
}

// ParseFramedMsg parse the provided buffer and returns a frame of the format
// msgLength+msg and any remaining bytes in that buffer.
func ParseFramedMsg(b []byte, maxLen uint32) ([]byte, []byte, error) {
	// If the size field is not complete, return the provided buffer as
	// remaining buffer.
	length, sufficientBytes := parseMessageLength(b)
	if !sufficientBytes {
		return nil, b, nil
	}
	if length > maxLen {
		return nil, nil, fmt.Errorf("received the frame length %d larger than the limit %d", length, maxLen)
	}
	if len(b) < int(length)+4 { // account for the first 4 msg length bytes.
		// Frame is not complete yet.
		return nil, b, nil
	}
	return b[:MsgLenFieldSize+length], b[MsgLenFieldSize+length:], nil
}

// parseMessageLength returns the message length based on frame header. It also
// returns a boolean indicating if the buffer contains sufficient bytes to parse
// the length header. If there are insufficient bytes, (0, false) is returned.
func parseMessageLength(b []byte) (uint32, bool) {
	if len(b) < MsgLenFieldSize {
		return 0, false
	}
	msgLenField := b[:MsgLenFieldSize]
	return binary.LittleEndian.Uint32(msgLenField), true
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Ensure the peer uses a compatible, uncorrupted ALTS record implementation.
  2. If this is a test, lower the amount of data per record to stay under 1 MiB.
  3. Treat this as a connection-fatal error: close and re-establish the ALTS connection.

Example fix

// before: test sends a frame of 2 MiB
// after: keep ALTS records <= 1 MiB (altsRecordLengthLimit)
frame := makeFrame(payload[:1<<20])
Defensive patterns

Strategy: try-catch

Try / catch

if _, _, err := conn.ParseFramedMsg(buf, altsRecordLengthLimit); err != nil {
    // oversized/malformed ALTS record: tear down the connection
    log.Printf("closing ALTS conn: %v", err)
    altsConn.Close()
}

Prevention

When it happens

Trigger: The ALTS peer (or a man-in-the-middle / corrupted stream) sends a record whose length header claims > 1 MiB. The read loop in record.go calls ParseFramedMsg on each chunk and surfaces this.

Common situations: A buggy or malicious peer; stream corruption after a TLS/ALTS failure; an interop test sending an oversized frame; a protocol implementation mismatch producing giant records.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/22fee33de8dad484. Report an issue: GitHub.