{"record":{"id":"c8bdfce1a275c397","repo":"vercel/next.js","slug":"key-block-too-short-for-entry-count-entries","errorCode":null,"errorMessage":"key block too short for {entry_count} entries","messagePattern":"key block too short for (.+?) entries","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"turbopack/crates/turbo-persistence/src/static_sorted_file.rs","lineNumber":616,"sourceCode":"\n    /// Looks up a key in a key block and the value in a value block.\n    ///\n    /// If `FIND_ALL` is false, returns after finding the first match.\n    /// If `FIND_ALL` is true, collects all entries with the same key.\n    fn lookup_variable_key_block<K: QueryKey, const FIND_ALL: bool>(\n        &self,\n        block: &[u8],\n        key_hash: u64,\n        key: &K,\n        layout: KeyBlockLayout,\n        reader: ArcBlockCacheReader<'_>,\n    ) -> Result<SstLookupResult> {\n        let hash_len = layout.hash_len();\n        ensure!(block.len() >= 4, \"key block too short\");\n        let entry_count = be::read_u24(&block[1..]) as usize;\n        let data = &block[4..];\n        let table_len = entry_count * key_block_table_stride(hash_len);\n        ensure!(\n            data.len() >= table_len,\n            \"key block too short for {entry_count} entries\"\n        );\n        let offsets = &data[..table_len];\n        let entries = &data[table_len..];\n\n        self.lookup_block_inner::<K, FIND_ALL>(entry_count, key_hash, key, layout, reader, |i| {\n            get_key_entry(offsets, entries, entry_count, i, hash_len)\n        })\n    }\n\n    /// Looks up a key in a fixed-size key block.\n    ///\n    /// Fixed-size key blocks store entries at predictable offsets (no offset table),\n    /// enabling direct indexing during binary search.\n    fn lookup_fixed_key_block<K: QueryKey, const FIND_ALL: bool>(\n        &self,\n        block: &[u8],","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/vercel/next.js/blob/34433fd12ee8074ea3f47af9f36255c7390d0301/turbopack/crates/turbo-persistence/src/static_sorted_file.rs#L598-L634","documentation":"After reading the entry count from a variable-key block's header, turbo-persistence checks that the remaining bytes are large enough to hold entry_count offset-table entries of key_block_table_stride(hash_len) bytes each. The block claims more entries than its byte length can hold, so it is corrupt or written with a mismatched layout.","triggerScenarios":"A variable-key SST key block whose declared entry count times the table stride exceeds the block's data length — header/data mismatch from truncation or a format-version mismatch between writer and reader.","commonSituations":"Cache files produced by a different Turbopack version with a changed key-block table stride; partially written cache blocks after a crash.","solutions":["Delete the persistent cache directory and let it regenerate.","Clear the cache when upgrading or downgrading Next.js/Turbopack so on-disk formats always match the reader.","Verify no concurrent writer is interleaving into the same cache directory.","If reproducible on a fresh cache, report as a turbo-persistence layout bug."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  lookup(key);\n} catch (e) {\n  if (/key block too short for \\d+ entries/.test(String(e))) {\n    resetCache();\n  } else throw e;\n}","preventionTips":["Keep cache writer and reader on the same Turbopack version (clear cache on version switches).","Prevent concurrent builds from writing to one cache directory.","Rebuild the cache at the first sign of corruption rather than ignoring it."],"tags":["storage","corruption","cache","rust"],"backgroundTag":"internal-invariant-violation","analyzedSha":"34433fd12ee8074ea3f47af9f36255c7390d0301","analyzedAt":"2026-09-20T18:20:20.576Z","contentChangedAt":"2026-09-20T18:20:20.576Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}