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

  1. Raise fetch.message.maxBytes (consumer) and message.max.bytes (broker) so single batches are not split across fetches.
  2. Check broker logs for 'Premature end of stream' or connection resets on the affected client; review network/MTU and TLS configuration.
  3. 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.
  4. 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

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


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/80acd67e667522de.json. Report an issue: GitHub.