apache/cassandra · error · EOFException

EOF after <skipped> bytes out of <n>

Error message

EOF after <skipped> bytes out of <n>

What it means

DataInputPlus.skipBytesFully(n) is a strict skip: it calls skipBytes(n) and throws EOFException if fewer bytes could be skipped than requested, guaranteeing callers that the stream is positioned exactly n bytes past the start and that the underlying source still had the data.

Source

Thrown at src/java/org/apache/cassandra/io/util/DataInputPlus.java:126

                     | (readByte() & 0xffL);
            case 8: return readLong();
            default: throw new IllegalArgumentException();
        }
    }

    /**
     * Always skips the requested number of bytes, unless EOF is reached
     *
     * @param n number of bytes to skip
     * @return number of bytes skipped
     */
    public int skipBytes(int n) throws IOException;

    public default void skipBytesFully(int n) throws IOException
    {
        int skipped = skipBytes(n);
        if (skipped != n)
            throw new EOFException("EOF after " + skipped + " bytes out of " + n);
    }

    @Override
    default byte readByte() throws IOException
    {
        return (byte) readUnsignedByte();
    }

    @Override
    default boolean readBoolean() throws IOException
    {
        return readUnsignedByte() != 0;
    }

    @Override
    default short readShort() throws IOException
    {
        int ch1 = readUnsignedByte();

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Treat the file/segment as truncated: stop reading at the last known-good offset (e.g. use CommitLogDescriptor/segment checksums to find the safe end).
  2. Restore or repair the data file from replica/backup if the corrupted source must be recovered.
  3. Verify reader and writer use the same serialization format/version; a mismatched schema can make lengths bogus.
  4. Catch EOFException in the streaming path and skip the damaged record rather than failing the whole operation.

Example fix

// before
in.skipBytesFully(rowBodySize);
// after
try {
    in.skipBytesFully(rowBodySize);
} catch (EOFException e) {
    logger.warn("Truncated record, aborting read at {}", in); 
    throw e; // or stop processing this segment
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check declared length against remaining bytes when the input exposes it
// e.g. if (declaredLength > input.availableBytes()) throw before skipping

Try / catch

try { input.skipBytesFully(n); }
catch (EOFException e) { abortSegment(e); /* stop at last good offset */ }

Prevention

When it happens

Trigger: Skipping a row body / cell value / serialized field whose declared length exceeds the remaining bytes in the stream — typically reading a truncated or corrupted SSTable row, commit log segment, or handoff file; or a length field read incorrectly due to format mismatch.

Common situations: Streaming/compacting a truncated SSTable; replaying a partially flushed commit log; reading inter-node message or hinted-handoff data cut short by a crash; deserializing with a serializer whose layout doesn't match the written one.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/6d6bca827e393745. Report an issue: GitHub.