{"record":{"id":"da8f9952fcd8ce70","repo":"ruvnet/ruflo","slug":"kv-cache-file-missing-sha256-footer","errorCode":null,"errorMessage":"KV cache file missing SHA256 footer","messagePattern":"KV cache file missing SHA256 footer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/gguf-engine.ts","lineNumber":412,"sourceCode":"    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;\n    }\n\n    // Verify footer hash (mandatory)\n    if (offset + 32 > data.length) {\n      throw new Error('KV cache file missing SHA256 footer');\n    }\n    const stored = data.subarray(offset, offset + 32);\n    const computed = createHash('sha256').update(data.subarray(44, offset)).digest();\n    if (!stored.equals(computed)) throw new Error('KV cache integrity check failed: hash mismatch');\n\n    this.kvCache = entries;\n    if (this.config.verbose) console.log(`[gguf-engine] KV cache loaded: ${entries.size} entries`);\n  }\n\n  /** Return metadata for all loaded models. */\n  getLoadedModels(): GgufMetadata[] { return Array.from(this.loadedModels.values()); }\n\n  /** Store a key-value pair in the in-memory KV cache. */\n  setKvEntry(key: string, value: Buffer): void { this.kvCache.set(key, value); }\n\n  /** Retrieve a key-value pair from the in-memory KV cache. */\n  getKvEntry(key: string): Buffer | undefined { return this.kvCache.get(key); }\n","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/appliance/gguf-engine.ts#L394-L430","documentation":"Thrown by loadKvCache after the entry loop when offset + 32 > data.length — the file has no room for the mandatory 32-byte SHA-256 footer. The footer is the integrity check for all entry data, so its absence means the file is incomplete or was not produced by a conformant writer.","triggerScenarios":"All declared entries were consumed but the file ends without the trailing 32-byte SHA-256 digest — e.g. persistKvCache was interrupted after writing entries but before (or during) the footer, or the file was trimmed by an external process.","commonSituations":"Crash during the final Buffer.concat/write of persistKvCache (footer is the last component); a tool that stripped trailing bytes; a cache written by an older writer that did not emit a footer (in which case version mismatch would normally fire first).","solutions":["Regenerate the cache with persistKvCache and confirm it completes (atomic write-then-rename prevents half-footers).","Delete the footerless file and cold-start.","Treat missing-footer as recoverable in loadKvCache's caller (catch and continue without cache).","Verify no external process (backup/cleanup agent) is truncating cache files."],"exampleFix":"// before\nawait engine.loadKvCache(path);\n\n// after\ntry {\n  await engine.loadKvCache(path);\n} catch (e) {\n  if (e instanceof Error && /missing SHA256 footer/.test(e.message)) {\n    logger.warn({ path }, 'KV cache missing footer; regenerating');\n    await fsUnlink(path).catch(() => {});\n  } else throw e;\n}","handlingStrategy":"fallback","validationCode":"// Ensure the file has room for the 32-byte footer:\nconst data = await readFile(path);\nif (data.length < 44 + 32) {\n  await fsUnlink(path).catch(() => {});\n  return; // cannot contain header + footer\n}\nawait engine.loadKvCache(path);","typeGuard":"function hasRoomForFooter(size: number): boolean {\n  return size >= 44 + 32;\n}","tryCatchPattern":"try {\n  await engine.loadKvCache(path);\n} catch (e) {\n  if (e instanceof Error && /missing SHA256 footer/.test(e.message)) {\n    await fsUnlink(path).catch(() => {});\n    return;\n  }\n  throw e;\n}","preventionTips":["Atomic writes guarantee the footer lands.","Regenerate caches missing a footer.","Confirm no external process trims cache files.","Cold-start on missing footer."],"tags":["gguf","kv-cache","integrity","sha256"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}