vercel/next.js · error

index block of .sst is too short ( bytes)

Error message

index block {} of {:08}.sst is too short ({} bytes)

What it means

turbo-persistence validates, while parsing an SST file, that the block flagged as the index block is at least INDEX_BLOCK_HEADER_SIZE bytes. This ensure! fails when the index block read from the file (or block cache) is truncated or corrupt, so the persistence layer cannot trust its structure.

Solutions

  1. Delete the corrupted cache directory (the persistent cache location for Turbopack) and let it be rebuilt on the next build.
  2. Verify no other process concurrently writes to the cache directory while builds run.
  3. Check available disk space and filesystem health for the volume holding the cache.
  4. If reproducible, capture the file and report it as a turbo-persistence corruption bug.
Defensive patterns

Strategy: fallback

Validate before calling

if (fs.existsSync(cacheDir) && !isCacheDirHealthy(cacheDir)) {
  fs.rmSync(cacheDir, { recursive: true, force: true });
}

Try / catch

try {
  runBuildWithCache(cacheDir);
} catch (e) {
  if (/is too short \(\d+ bytes\)/.test(String(e))) {
    fs.rmSync(cacheDir, { recursive: true, force: true });
    runBuildWithCache(cacheDir); // rebuild fresh cache
  } else throw e;
}

Prevention

When it happens

Trigger: Opening/reading a {:08}.sst file whose index block is shorter than the fixed header size — typically after a truncated write, disk-full condition, or manual tampering with the cache directory.

Common situations: A Turbopack persistent cache directory corrupted by a crash or power loss mid-write; copying or rsyncing a cache directory while it was being written; a disk with bad sectors.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of vercel/next.js@34433fd12e (2026-09-20). Data as JSON: /api/errors/ff78a8b3f002834d. Report an issue: GitHub.

Appendix: source

Thrown at turbopack/crates/turbo-persistence/src/static_sorted_file.rs:409

            uncompressed_length == 0,
            "index block {} of {:08}.sst is compressed, but index blocks are always written \
             uncompressed",
            block_index,
            meta.sequence_number
        );
        // Verified here rather than through `verified_blocks`: this is the one and only read of
        // this block's bytes, so the bitmap would never save any work for it.
        let data = &*block;
        verify_checksum(meta, data, checksum, block_index)?;

        ensure!(
            data.len() >= INDEX_BLOCK_HEADER_SIZE,
            "index block {} of {:08}.sst is too short ({} bytes)",
            block_index,
            meta.sequence_number,
            data.len()
        );
        ensure!(
            be::read_u8(data) == BLOCK_TYPE_INDEX,
            "block {} of {:08}.sst is the last block but not an index block (type {})",
            block_index,
            meta.sequence_number,
            be::read_u8(data)
        );
        let first_block = be::read_u16(&data[1..]);
        let entry_bytes = &data[INDEX_BLOCK_HEADER_SIZE..];
        ensure!(
            entry_bytes.len().is_multiple_of(INDEX_BLOCK_ENTRY_SIZE),
            "index block {} of {:08}.sst has {} trailing bytes past its last entry",
            block_index,
            meta.sequence_number,
            entry_bytes.len() % INDEX_BLOCK_ENTRY_SIZE
        );

        let entries = match backing {
            // Store a range, not the slice: `StaticSortedFile` owns the mmap these bytes live in.

View on GitHub (pinned to 34433fd12e)