vercel/next.js · error

mixed-type fixed key block too short

Error message

mixed-type fixed key block too short

What it means

When a fixed-size key block uses the mixed value type, fixed_value_layout expects at least 7 bytes so it can read the value footprint byte at offset 6. This error means the block buffer is shorter than the minimum header size required by the mixed-type layout, i.e. the block is truncated or corrupt.

Solutions

  1. Delete the affected cache/store directory and rebuild the cache.
  2. Check for crashes or forced kills during write; ensure writes complete and the process is not terminated mid-flush.
  3. If reproducible, verify reader/writer version compatibility and file an upstream bug with the reproduction steps.
Defensive patterns

Strategy: fallback

Validate before calling

// Validate persisted file integrity before decode
function blockIsReadable(block: Buffer): boolean {
  return block.length >= 7 // minimum mixed-type fixed key block header
}

Try / catch

try {
  const layout = fixedValueLayout(block, headerType)
} catch (e) {
  if (String(e).includes('too short')) {
    // fall back to rebuilding the store from source data
  } else throw e
}

Prevention

When it happens

Trigger: Calling fixed_value_layout (during block decode) with header_type == FIXED_KEY_BLOCK_MIXED_VALUE_TYPE and block.len() < 7; caused by truncated or malformed persisted data in a static sorted file.

Common situations: Incomplete cache writes after a crash or kill, corrupted cache files, or a reader opened against data written by an incompatible format version.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

///
/// All entries have the same key size and value type, so positions are computed
/// arithmetically with no offset table indirection.
/// How a fixed-size key block encodes its entry values, decoded from the block header.
struct FixedValueLayout {
    /// The type shared by every entry, or `None` if each entry carries its own type byte.
    value_type: Option<u8>,
    /// Value bytes per entry, including any per-entry type byte.
    val_size: usize,
    /// Total header size, which the entry data follows.
    header_size: usize,
}

/// Decodes the value layout from a fixed-size key block header.
fn fixed_value_layout(block: &[u8], header_type: u8) -> Result<FixedValueLayout> {
    if header_type == FIXED_KEY_BLOCK_MIXED_VALUE_TYPE {
        // Mixed-type block: the value size follows the header's type byte, and each entry
        // carries its own type.
        ensure!(block.len() >= 7, "mixed-type fixed key block too short");
        // Validate the value footprint byte
        let value_footprint = be::read_u8(&block[6..]) as usize;
        ensure!(
            value_footprint <= MAX_INLINE_VALUE_SIZE,
            "mixed-type fixed key block claims a {value_footprint} byte value footprint, over the \
             {MAX_INLINE_VALUE_SIZE} byte maximum"
        );
        Ok(FixedValueLayout {
            value_type: None,
            // +1 for the per-entry type byte, which is part of the stride.
            val_size: value_footprint + 1,
            header_size: 7,
        })
    } else {
        Ok(FixedValueLayout {
            value_type: Some(header_type),
            val_size: entry_val_size(header_type)?,
            header_size: 6,

View on GitHub (pinned to 34433fd12e)