{"record":{"id":"fc50495825ce1855","repo":"ruvnet/ruflo","slug":"kv-cache-integrity-check-failed-hash-mismatch","errorCode":null,"errorMessage":"KV cache integrity check failed: hash mismatch","messagePattern":"KV cache integrity check failed: hash mismatch","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/gguf-engine.ts","lineNumber":416,"sourceCode":"    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\n  /** Release resources, unload models, and optionally persist the KV cache. */\n  async shutdown(): Promise<void> {\n    if (this.config.kvCachePath && this.kvCache.size > 0) {\n      try { await this.persistKvCache(this.config.kvCachePath); }","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/appliance/gguf-engine.ts#L398-L434","documentation":"Thrown by loadKvCache when the stored 32-byte footer does not equal the SHA-256 computed over data.subarray(44, offset) (the entry region). This is the strongest integrity check: the cache content has been altered, truncated, extended, or corrupted after persistKvCache wrote it. A mismatch means the entries cannot be trusted.","triggerScenarios":"Any modification to the entry bytes between offset 44 and the footer without recomputing the footer — manual editing, disk corruption, a partial overwrite, or two writers racing on the same path. Also fires if the persistKvCache logic itself produced inconsistent header/footer (a bug), but on-disk mutation is far more common.","commonSituations":"Disk/filesystem corruption; two processes writing the same cache path concurrently; a cache copied between systems with a transfer that altered bytes; an older/newer writer with a different hash scope (version mismatch usually precedes this). The check is mandatory, so there is no bypass.","solutions":["Delete the corrupt cache and regenerate via persistKvCache (KV caches are disposable derived data).","Ensure only one engine instance writes a given cache path; serialize or namespace caches per model/instance.","Verify file transfer integrity (compare checksums) when moving caches between machines.","If this reproduces on freshly written files, suspect the persistKvCache buffer-concatenation/hash scope and file a bug; do not weaken the integrity check."],"exampleFix":"// before\nawait engine.loadKvCache(path);\n\n// after\ntry {\n  await engine.loadKvCache(path);\n} catch (e) {\n  if (e instanceof Error && /integrity check failed/.test(e.message)) {\n    logger.error({ path }, 'KV cache hash mismatch; discarding');\n    await fsUnlink(path).catch(() => {});\n  } else throw e;\n}","handlingStrategy":"fallback","validationCode":"// The engine already computes and compares the hash. Callers cannot cheaply\n// pre-verify faster than the engine; instead, treat mismatch as disposable:\n// delete and regenerate. (See tryCatchPattern.)","typeGuard":"// No caller-side type guard; integrity is verified inside loadKvCache.","tryCatchPattern":"try {\n  await engine.loadKvCache(path);\n} catch (e) {\n  if (e instanceof Error && /integrity check failed/.test(e.message)) {\n    logger.error({ path }, 'KV cache hash mismatch; discarding');\n    await fsUnlink(path).catch(() => {});\n    return;\n  }\n  throw e;\n}","preventionTips":["Never weaken or skip the SHA-256 check.","Ensure only one writer per cache path.","Verify checksums when transferring caches between hosts.","Discard and rebuild on any hash mismatch."],"tags":["gguf","kv-cache","integrity","sha256","corruption"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}