grpc/grpc-java · error · IllegalArgumentException
Invalid frame length ${dataLength}
Error message
Invalid frame length ${dataLength} What it means
AltsFraming's parser reads a little-endian 4-byte frame length header and validates it: the declared data length must be at least FRAME_MESSAGE_TYPE_HEADER_SIZE and at most MAX_DATA_LENGTH. A length outside that range means the byte stream is corrupt or not an ALTS frame, so parsing fails fast with IllegalArgumentException.
Source
Thrown at alts/src/main/java/io/grpc/alts/internal/AltsFraming.java:287
if (isComplete) {
return true;
}
// Read enough bytes to determine the length
while (buffer.position() < FRAME_LENGTH_HEADER_SIZE && input.hasRemaining()) {
buffer.put(input.get());
}
// If we have enough bytes to determine the length, read the length and ensure that our
// internal buffer is large enough.
if (buffer.position() == FRAME_LENGTH_HEADER_SIZE && input.hasRemaining()) {
ByteBuffer bufferAlias = buffer.duplicate();
((Buffer) bufferAlias).flip();
bufferAlias.order(ByteOrder.LITTLE_ENDIAN);
int dataLength = bufferAlias.getInt();
if (dataLength < FRAME_MESSAGE_TYPE_HEADER_SIZE || dataLength > MAX_DATA_LENGTH) {
throw new IllegalArgumentException("Invalid frame length " + dataLength);
}
// Maybe resize the buffer
int frameLength = dataLength + FRAME_LENGTH_HEADER_SIZE;
if (buffer.capacity() < frameLength) {
buffer = ByteBuffer.allocate(frameLength);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(dataLength);
}
((Buffer) buffer).limit(frameLength);
}
// TODO: Similarly extract and check message type.
// Read the remaining data into the internal buffer.
copy(buffer, input);
if (!buffer.hasRemaining()) {
((Buffer) buffer).flip();
isComplete = true;View on GitHub (pinned to 64daddc1f3)
Solutions
- Verify the peer is speaking the same ALTS framing protocol version
- Check the code producing/consuming the stream for byte misalignment (e.g. incorrect slice/offset of the length header)
- If dataLength is 0 confirm the writer always includes the message-type header, not just the payload
- Reset the connection — once the frame stream is desynchronized it cannot be recovered
Example fix
// writer side: before buf.putInt(payload.length); // after — include message type + payload in the length field int dataLength = FRAME_MESSAGE_TYPE_HEADER_SIZE + payload.length; buf.putInt(dataLength);
Defensive patterns
Strategy: try-catch
Validate before calling
int len = readLittleEndianInt32(header);
if (len < FRAME_MESSAGE_TYPE_HEADER_SIZE || len > MAX_DATA_LENGTH) {
throw new IOException("corrupt ALTS frame length: " + len);
} Type guard
null
Try / catch
try {
parser.readBytes(input);
} catch (IllegalArgumentException e) {
// framing desynchronized: discard the stream and reset the connection
connection.reset();
} Prevention
- Ensure the length field includes the message-type header
- Never re-slice frame buffers without the 4-byte header offset
- Don't feed non-ALTS byte streams into the ALTS parser
When it happens
Trigger: Feeding the ALTS frame parser bytes whose 4-byte length prefix decodes below the message-type header size (including 0/negative) or above MAX_DATA_LENGTH — i.e. desynchronized stream, corrupted framing, or wrong protocol bytes fed to the parser.
Common situations: Handshaker/transport byte-stream corruption, an off-by-N misalignment while copying frame bytes, or piping a non-ALTS stream into the ALTS frame parser in unit tests.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Received an unexpected response.
- No ALTS context information found
- Can't set TLS settings for ALTS
- Counter has overflowed.
- Could not get enough key data from the handshake.
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/bb56649b27de7de8.
Report an issue: GitHub.