{"record":{"id":"11e8e20fc69f8d38","repo":"ruvnet/ruflo","slug":"no-ruvbot-memory-instance-attached-call-attachmem","errorCode":null,"errorMessage":"No ruvbot memory instance attached. Call attachMemory() before performing memory operations.","messagePattern":"No ruvbot memory instance attached\\. Call attachMemory\\(\\) before performing memory operations\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/guidance/src/ruvbot-integration.ts","lineNumber":595,"sourceCode":"  /**\n   * Get the count of governed operations.\n   */\n  get operationCount(): number {\n    return this.operationLog.length;\n  }\n\n  /**\n   * Clear the operation log.\n   */\n  clearLog(): void {\n    this.operationLog = [];\n  }\n\n  // ===== Private Helpers =====\n\n  private ensureMemoryAttached(): void {\n    if (!this.ruvbotMemory) {\n      throw new Error(\n        'No ruvbot memory instance attached. Call attachMemory() before ' +\n        'performing memory operations.',\n      );\n    }\n  }\n}\n\n// ============================================================================\n// RuvBotGuidanceBridge\n// ============================================================================\n\n/**\n * Bridges a ruvbot instance with the @claude-flow/guidance control plane.\n *\n * Wires ruvbot event hooks to guidance enforcement and trust systems:\n *\n * - `message`        -> EnforcementGates (secrets, destructive ops) + AIDefence\n * - `agent:spawn`    -> ManifestValidator","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/guidance/src/ruvbot-integration.ts#L577-L613","documentation":"Thrown by RuvBotMemoryAdapter in @claude-flow/guidance when a governed memory operation (read, write, or delete) is invoked before a ruvbot memory instance has been attached. The adapter proxies every operation to the wrapped RuvBotMemory after running it through the MemoryWriteGate, so it refuses to operate on a null delegate. It is a wiring/setup error, not a runtime data error.","triggerScenarios":"Constructing RuvBotMemoryAdapter(memoryGate, coherenceScheduler) and then calling adapter.read(key, ns), adapter.write(key, ns, value, authority), or adapter.delete(...) without ever calling adapter.attachMemory(memory). The guard ensureMemoryAttached() runs as the first statement of every proxied operation.","commonSituations":"Setup code copied from docs that shows construction but omits the attach step; DI containers that build the adapter lazily and skip the second-phase attach; unit tests that instantiate the adapter directly with real gates but forget to attach a mock RuvBotMemory.","solutions":["Call adapter.attachMemory(ruvbotMemory) with an object implementing RuvBotMemory (read/write/delete) immediately after constructing the adapter","Wrap construction and attachment in a single factory function so the adapter can never be handed out un-attached","In tests, attach a stub memory: adapter.attachMemory({ read: async () => value, write: async () => {}, delete: async () => {} })"],"exampleFix":"// before\nconst adapter = new RuvBotMemoryAdapter(memoryGate, scheduler);\nawait adapter.read('key', 'ns'); // throws: no ruvbot memory attached\n\n// after\nconst adapter = new RuvBotMemoryAdapter(memoryGate, scheduler);\nadapter.attachMemory(ruvbotMemory); // required before any read/write/delete\nawait adapter.read('key', 'ns');","handlingStrategy":"validation","validationCode":"// Make attachment atomic with construction so the error cannot fire later\nfunction createGovernedMemory(\n  memoryGate: MemoryWriteGate,\n  scheduler: CoherenceScheduler,\n  memory: RuvBotMemory,\n): RuvBotMemoryAdapter {\n  const adapter = new RuvBotMemoryAdapter(memoryGate, scheduler);\n  adapter.attachMemory(memory); // mandatory before read/write/delete\n  return adapter;\n}","typeGuard":"// ruvbotMemory is private; track attachment externally\nconst attachedMemories = new WeakSet<RuvBotMemoryAdapter>();\nfunction hasMemoryAttached(adapter: RuvBotMemoryAdapter): boolean {\n  return attachedMemories.has(adapter);\n}\n// after adapter.attachMemory(m): attachedMemories.add(adapter);","tryCatchPattern":"try {\n  await adapter.write(key, ns, value, authority);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('attachMemory()')) {\n    throw new Error('Setup bug: adapter used before attachMemory()', { cause: e });\n  }\n  throw e;\n}","preventionTips":["Never hand out a RuvBotMemoryAdapter from a factory without attaching memory in the same call","Treat attachMemory as part of the constructor contract in review checklists","In tests, always attach a stub RuvBotMemory right after construction"],"tags":["ruvbot","memory","guidance","initialization","dependency-injection"],"backgroundTag":"dependency-not-initialized","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}