apache/kafka · error · InvalidRecordException
Reached end of input stream before skipping all bytes. Remai
Error message
Reached end of input stream before skipping all bytes. Remaining bytes:{} What it means
Thrown by the private skipBytes helper when InputStream.skip() returns 0 and the following read() returns -1, i.e. the stream hit end-of-stream before all the key/value/header-value bytes of a record could be skipped. It indicates a truncated record body on the streaming partial-read path.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/record/internal/DefaultRecord.java:447
* No-op for case where bytesToSkip <= 0. This could occur for cases where field is expected to be null.
* @throws InvalidRecordException if end of stream is encountered before we could skip required bytes.
* @throws IOException is an I/O error occurs while trying to skip from InputStream.
*
* @see java.io.InputStream#skip(long)
*/
private static void skipBytes(InputStream in, int bytesToSkip) throws IOException {
if (bytesToSkip <= 0) return;
// Starting JDK 12, this implementation could be replaced by InputStream#skipNBytes
while (bytesToSkip > 0) {
int ns = (int) in.skip(bytesToSkip);
if (ns > 0 && ns <= bytesToSkip) {
// adjust number to skip
bytesToSkip -= ns;
} else if (ns == 0) { // no bytes skipped
// read one byte to check for EOS
if (in.read() == -1) {
throw new InvalidRecordException("Reached end of input stream before skipping all bytes. " +
"Remaining bytes:" + bytesToSkip);
}
// one byte read so decrement number to skip
bytesToSkip--;
} else { // skipped negative or too many bytes
throw new IOException("Unable to skip exactly");
}
}
}
private static Header[] readHeaders(ByteBuffer buffer, int numHeaders) {
Header[] headers = new Header[numHeaders];
for (int i = 0; i < numHeaders; i++) {
int headerKeySize = ByteUtils.readVarint(buffer);
if (headerKeySize < 0)
throw new InvalidRecordException("Invalid negative header key size " + headerKeySize);
ByteBuffer headerKeyBuffer = Utils.readBytes(buffer, headerKeySize);View on GitHub (pinned to c31c9215e1)
Solutions
- Raise fetch.message.maxBytes (consumer) and message.max.bytes (broker) so single batches are not split across fetches.
- Check broker logs for 'Premature end of stream' or connection resets on the affected client; review network/MTU and TLS configuration.
- If reading from a local segment, verify the file length on disk matches the log segment metadata; recover from an in-sync replica if truncated.
- Reproduce with kafka-dump-log on the same segment; if it succeeds the issue is in the transport, if it fails the segment itself is short.
Defensive patterns
Strategy: try-catch
Validate before calling
// If you control the InputStream, you can probe with available() before
// skipBytes — but available() is advisory. Safer: read into a bounded buffer
// whose length you have already validated against sizeOfBodyInBytes.
if (input.available() < bytesStillToSkip) { /* likely EOF; abort gracefully */ } Try / catch
try {
PartialDefaultRecord r = DefaultRecord.readPartiallyFrom(input, baseOffset, baseTimestamp, baseSequence, logAppendTime);
} catch (InvalidRecordException | IOException e) {
// reached EOS while skipping key/value/header bytes
LOG.warn("Truncated record stream near offset {}", baseOffset, e);
} Prevention
- Ensure the InputStream is fully buffered before partial parsing; copy network streams into a ByteArrayInputStream of known length first.
- Validate the declared record body size against the remaining batch bytes before descending into records.
- Treat early EOF as a sign of network truncation or on-disk corruption; quarantine the batch rather than retrying blindly.
When it happens
Trigger: Raised at DefaultRecord.java:446-448 inside skipBytes(InputStream, int) during readPartiallyFrom, when the declared keySize/valueSize/headerKeySize/headerValueSize exceeds the bytes actually available in the stream. Reached when skip() makes no progress for one of those fields and a probe read confirms EOF.
Common situations: Network read truncated mid-batch (broker closed the connection, fetch.message.maxBytes cut a batch in two, TLS hiccup), a log segment truncated by an unclean leader election or disk-full shutdown, or a custom InputStream that signals EOF early. Distinct from corruption: the bytes simply are not there.
Related errors
- Invalid record size: expected {} bytes in record payload, bu
- Found invalid number of record headers {}
- Found invalid number of record headers. {} is larger than th
- Invalid record size: expected to read {} bytes in record pay
- Found invalid record structure
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/80acd67e667522de.json.
Report an issue: GitHub.