{"record":{"id":"c2558ce168f737c5","repo":"ruvnet/ruflo","slug":"kv-cache-file-too-small","errorCode":null,"errorMessage":"KV cache file too small","messagePattern":"KV cache file too small","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/gguf-engine.ts","lineNumber":389,"sourceCode":"      entryBufs.push(hdr, keyBuf, value);\n    }\n    const entryData = Buffer.concat(entryBufs);\n    const footer = createHash('sha256').update(entryData).digest();\n\n    const header = Buffer.alloc(44);\n    header.writeUInt32LE(RVKV_MAGIC, 0);\n    header.writeUInt32LE(RVKV_VERSION, 4);\n    modelHash.copy(header, 8);\n    header.writeUInt32LE(this.kvCache.size, 40);\n\n    await writeFile(path, Buffer.concat([header, entryData, footer]));\n    if (this.config.verbose) console.log(`[gguf-engine] KV cache persisted: ${this.kvCache.size} entries`);\n  }\n\n  /** Restore KV cache from an RVF-compatible binary file. */\n  async loadKvCache(inputPath: string): Promise<void> {\n    const data = await readFile(inputPath);\n    if (data.length < 44) throw new Error('KV cache file too small');\n\n    const magic = data.readUInt32LE(0);\n    if (magic !== RVKV_MAGIC) throw new Error(`Invalid KV cache magic: 0x${magic.toString(16)}`);\n    const version = data.readUInt32LE(4);\n    if (version !== RVKV_VERSION) throw new Error(`Unsupported KV cache version: ${version}`);\n\n    const entryCount = data.readUInt32LE(40);\n    let offset = 44;\n    const entries = new Map<string, Buffer>();\n\n    for (let i = 0; i < entryCount; i++) {\n      if (offset + 8 > data.length) throw new Error('KV cache file truncated');\n      const keyLen = data.readUInt32LE(offset);\n      const valLen = data.readUInt32LE(offset + 4);\n      offset += 8;\n      if (offset + keyLen + valLen > data.length) throw new Error('KV cache file truncated');\n      entries.set(data.toString('utf-8', offset, offset + keyLen), Buffer.from(data.subarray(offset + keyLen, offset + keyLen + valLen)));\n      offset += keyLen + valLen;","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/appliance/gguf-engine.ts#L371-L407","documentation":"loadKvCache requires at least the 44-byte RVKV header (magic u32 + version u32 + 32-byte model SHA-256 + entry-count u32); a shorter file is rejected before any parsing. In practice the file is empty or nearly empty — the result of a failed/interrupted persist or a wrong path.","triggerScenarios":"loadKvCache on a 0-43 byte file: an empty artifact left by a crashed persistKvCache, a partially copied cache, or a path pointing at some other tiny file.","commonSituations":"Hard-killed processes between file creation and write completion; non-atomic copies of live caches; path typos landing on unrelated small files.","solutions":["Stat the file first and require size >= 44 before loading; regenerate otherwise","Delete the bad cache and re-persist with persistKvCache — the cache is disposable state","Make persistence atomic (write temp file, then rename) so partial files never appear at the canonical path"],"exampleFix":"// before\nawait engine.loadKvCache(cachePath);\n\n// after\nconst { size } = await stat(cachePath);\nif (size < 44) {\n  await engine.persistKvCache(cachePath); // rebuild cold cache\n} else {\n  await engine.loadKvCache(cachePath);\n}","handlingStrategy":"validation","validationCode":"const { size } = await stat(cachePath);\nif (size < 44) {\n  await engine.persistKvCache(cachePath); // rebuild: header alone is 44 bytes\n} else {\n  await engine.loadKvCache(cachePath);\n}","typeGuard":null,"tryCatchPattern":"try { await engine.loadKvCache(cachePath); }\ncatch (e) { if (e instanceof Error && e.message === 'KV cache file too small') { await engine.persistKvCache(cachePath); } else throw e; }","preventionTips":["Write caches atomically (temp file + rename) so partial files never exist at the load path","Stat cache files before loading and regenerate undersized ones","Treat KV caches as disposable: losing one costs only a warm-up"],"tags":["kv-cache","truncated-file","binary-parsing","nodejs"],"backgroundTag":"truncated-file","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}