{"record":{"id":"5f8ec3d6591ed24b","repo":"ruvnet/ruflo","slug":"no-kv-cache-output-path-specified","errorCode":null,"errorMessage":"No KV cache output path specified","messagePattern":"No KV cache output path specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/appliance/gguf-engine.ts","lineNumber":362,"sourceCode":"            if (typeof chunk === 'string') yield chunk;\n            else if (chunk?.text) yield chunk.text;\n          }\n          return;\n        }\n      } catch { /* fall through to single-chunk fallback */ }\n    }\n    const response = await this.generate(request);\n    yield response.text;\n  }\n\n  /**\n   * Persist the KV cache to an RVF-compatible binary file.\n   * Format: RVKV magic | version u32 | model SHA-256 (32B) | entry count u32\n   *         entries: [key_len u32, key, val_len u32, val] | footer SHA-256 (32B)\n   */\n  async persistKvCache(outputPath: string): Promise<void> {\n    const path = outputPath || this.config.kvCachePath;\n    if (!path) throw new Error('No KV cache output path specified');\n\n    const modelHash = createHash('sha256').update(this.activeModelPath ?? 'no-model').digest();\n    const entryBufs: Buffer[] = [];\n    for (const [key, value] of this.kvCache) {\n      const keyBuf = Buffer.from(key, 'utf-8');\n      const hdr = Buffer.alloc(8);\n      hdr.writeUInt32LE(keyBuf.length, 0);\n      hdr.writeUInt32LE(value.length, 4);\n      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);","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/appliance/gguf-engine.ts#L344-L380","documentation":"GgufEngine.persistKvCache(outputPath) writes the RVF binary only when outputPath is truthy or the engine was constructed with config.kvCachePath; both empty throws. The output location is never inferred, so persisting requires an explicit argument or config value.","triggerScenarios":"Calling engine.persistKvCache('') or persistKvCache() on an engine built from a GgufEngineConfig that omits kvCachePath; config parsed from an env var that is unset, yielding undefined/empty string.","commonSituations":"Inline test configs omitting kvCachePath; empty-string defaults from config parsing; calling persist before the engine config was fully wired.","solutions":["Pass an explicit output path: await engine.persistKvCache('/cache/session.rvkv')","Or set kvCachePath in GgufEngineConfig when constructing the engine","Fail fast at startup: if KV persistence is enabled, require a non-empty kvCachePath before running"],"exampleFix":"// before\nconst engine = new GgufEngine({ contextSize: 2048 });\nawait engine.persistKvCache(''); // throws\n\n// after\nconst engine = new GgufEngine({ contextSize: 2048, kvCachePath: '/cache/session.rvkv' });\nawait engine.persistKvCache('/cache/session.rvkv');","handlingStrategy":"validation","validationCode":"const out = outputPath ?? engineConfig.kvCachePath;\nif (!out) throw new Error('kv cache path required for persistence');\nawait engine.persistKvCache(out);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set kvCachePath in GgufEngineConfig when persistence is intended","Validate config completeness at engine construction, not at persist time","Treat empty-string config values as missing (fail fast on startup)"],"tags":["gguf","kv-cache","configuration","missing-path","nodejs"],"backgroundTag":"missing-config-value","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"}