grpc/grpc-go · error
protocol
Error message
protocol %q: %v
What it means
Returned by conn.NewConnWithMaxFrameSize when the ALTSRecordFunc for the negotiated protocol was found and invoked, but returned an error during construction of the crypto instance. The wrapped error (%v) is the underlying crypto error. For the built-in ALTSRP_GCM_AES128_REKEY this means conn.NewAES128GCMRekey(side, key) failed.
Solutions
- Inspect the wrapped error message — for AES128GCMRekey it usually indicates a key-length problem; compare against the expected 44 bytes (keyLength map).
- Verify the GCP handshaker service and grpc-go versions are compatible.
- File a grpc-go issue with the wrapped error if the handshaker service is the standard GCP one and key data appears malformed.
- If using a custom ALTSRecordFunc, debug its constructor's validation logic.
Defensive patterns
Strategy: try-catch
Try / catch
// Crypto construction failures during ALTS setup are unrecoverable for the connection.
// Log the wrapped error and fail the RPC; gRPC will reconnect.
if err != nil {
log.Printf("ALTS crypto setup failed: %v", err)
return err
} Prevention
- Ensure handshaker service and grpc-go versions are compatible so key sizes match (44 bytes for AES128GCMRekey).
- When writing a custom ALTSRecordFunc, validate key length up front and return a clear error.
- Capture the wrapped error in logs to diagnose key-material issues.
When it happens
Trigger: The ALTS handshake delivers a key of incorrect length or invalid content for AES-128-GCM-Rekey, so NewAES128GCMRekey returns an error when deriving counters or setting up the AEAD. Reached during doHandshake -> NewConnWithMaxFrameSize on GCP.
Common situations: The handshaker service returned truncated or malformed key data; a custom ALTS record implementation with a bug in its constructor; memory corruption on the handshaker RPC; an interoperability issue with a non-Go handshaker that produces keys of a different size.
Related errors
- client-side RPC versions is not compatible with this…
- negotiated unknown next_protocol
- server-side RPC versions are not compatible with this…
- unknown resulted record protocol
- failed to establish stream to ALTS handshaker service
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/4052dafda2418cf4.
Report an issue: GitHub.
Appendix: source
Thrown at credentials/alts/internal/conn/record.go:151
constPool constBufferPool // stored as a field to avoid heap allocations.
}
// NewConn creates a new secure channel instance given the other party role and
// handshaking result.
func NewConn(c net.Conn, side core.Side, recordProtocol string, key []byte, protected []byte) (net.Conn, error) {
return NewConnWithMaxFrameSize(c, side, recordProtocol, key, protected, 0)
}
// NewConnWithMaxFrameSize creates a new secure channel instance given the
// other party role, handshaking result, and negotiated maximum frame size.
func NewConnWithMaxFrameSize(c net.Conn, side core.Side, recordProtocol string, key []byte, protected []byte, negotiatedMaxFrameSize int) (net.Conn, error) {
newCrypto := protocols[recordProtocol]
if newCrypto == nil {
return nil, fmt.Errorf("negotiated unknown next_protocol %q", recordProtocol)
}
crypto, err := newCrypto(side, key)
if err != nil {
return nil, fmt.Errorf("protocol %q: %v", recordProtocol, err)
}
overhead := MsgLenFieldSize + msgTypeFieldSize + crypto.EncryptionOverhead()
// Clamp maxRecordLen to be at least altsRecordDefaultLength.
maxRecordLen := max(altsRecordDefaultLength, negotiatedMaxFrameSize)
payloadLengthLimit := maxRecordLen - overhead
// We pre-allocate protected to be of size 32KB during initialization.
// We increase the size of the buffer by the required amount if it can't
// hold a complete encrypted record.
protectedHandle := readBufPool.Get(max(altsReadBufferInitialSize, len(protected)))
protectedBuf := *protectedHandle
// Copy additional data from hanshaker service.
copy(protectedBuf, protected)
protectedBuf = protectedBuf[:len(protected)]
altsConn := &conn{
Conn: c,
reader: readyreader.New(c),View on GitHub (pinned to 0c51461d27)