apache/cassandra · error · CorruptIndexException

Invalid block offset %d for postings block idx %d

Error message

Invalid block offset %d for postings block idx %d

What it means

PostingsReader.reBuffer() seeks to the block offset stored in the postings summary. Offsets < 4 are invalid because the first 4 bytes of an index component file must be CodecUtil's CODEC_MAGIC, so any valid block must start at or after byte 4. Hitting this means the summary offsets array is corrupt or the wrong component file is attached, and it is thrown as Lucene CorruptIndexException.

Source

Thrown at src/java/org/apache/cassandra/index/sai/disk/v1/postings/PostingsReader.java:328

        long id = currentFoRValues.get(postingIndex);
        postingsDecoded++;
        return Math.toIntExact(id);
    }

    private void advanceOnePosition(long nextPosting)
    {
        actualPosting = nextPosting;
        totalPostingsRead++;
        postingIndex++;
    }

    private void reBuffer() throws IOException
    {
        long pointer = summary.offsets.get(blockIndex);
        if (pointer < 4)
        {
            // the first 4 bytes must be CODEC_MAGIC
            throw new CorruptIndexException(String.format("Invalid block offset %d for postings block idx %d", pointer, blockIndex), input);
        }
        input.seek(pointer);

        long left = summary.numPostings - totalPostingsRead;
        assert left > 0;

        readFoRBlock(input);

        blockIndex++;
        postingIndex = 0;
    }

    private void readFoRBlock(IndexInput in) throws IOException
    {
        if (blockIndex == 0)
            actualPosting = in.readVLong();

        byte bitsPerValue = in.readByte();

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Rebuild the SAI index to regenerate postings and summary components.
  2. Verify checksums of the IndexComponent files and restore from a healthy snapshot.
  3. Ensure the PostingsReader is opened with the matching summary for the same posting list (correct component/segment).
Defensive patterns

Strategy: try-catch

Validate before calling

long off = summary.offsets.get(blockIndex); if (off < 4) failFast(); // pre-check before reader advances

Try / catch

try { iterator.next(); } catch (CorruptIndexException e) { log.error("Corrupt postings", e); markIndexCorrupt(index); }

Prevention

When it happens

Trigger: Advancing the postings iterator into a block whose summary.offsets.get(blockIndex) is < 4 (typically 0 or negative from an unwritten/truncated offsets entry).

Common situations: Truncated or zero-filled SAI postings files after a crash or disk failure, component file mix-ups (reading one component with another's summary), or bit-rot.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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