{"record":{"id":"262d0aa16601a1dc","repo":"n8n-io/n8n","slug":"episodic-memory-requires-a-storage-backend-that-im","errorCode":null,"errorMessage":"Episodic memory requires a storage backend that implements BuiltEpisodicMemoryStore.","messagePattern":"Episodic memory requires a storage backend that implements BuiltEpisodicMemoryStore\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/agents/src/sdk/memory.ts","lineNumber":128,"sourceCode":"\t\tconfig.observationalMemory.renderTokenBudget === undefined\n\t\t\t? {\n\t\t\t\t\t...config.observationalMemory,\n\t\t\t\t\trenderTokenBudget: config.observationLog.renderTokenBudget,\n\t\t\t\t}\n\t\t\t: config.observationalMemory;\n\tconst observationalMemory = resolveObservationalMemoryConfig(observationalMemoryConfig, options);\n\n\treturn normalizeMemoryConfig({\n\t\t...config,\n\t\tmemory: config.memory,\n\t\tobservationalMemory,\n\t\tepisodicMemory,\n\t});\n}\n\nexport function normalizeMemoryConfig(config: MemoryConfig): MemoryConfig {\n\tif (isEpisodicMemoryEnabled(config.episodicMemory) && !hasEpisodicMemoryStore(config.memory)) {\n\t\tthrow new Error(\n\t\t\t'Episodic memory requires a storage backend that implements BuiltEpisodicMemoryStore.',\n\t\t);\n\t}\n\n\tif (!config.observationalMemory) {\n\t\treturn config;\n\t}\n\n\tif (!hasObservationLogStore(config.memory)) {\n\t\tthrow new Error(\n\t\t\t'Observational memory requires a storage backend that implements BuiltObservationLogStore.',\n\t\t);\n\t}\n\n\treturn {\n\t\t...config,\n\t\tobservationLog: {\n\t\t\t...config.observationLog,","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/agents/src/sdk/memory.ts#L110-L146","documentation":"Thrown from normalizeMemoryConfig when episodic memory is enabled but the configured backend does not implement BuiltEpisodicMemoryStore. Capability is detected by hasEpisodicMemoryStore, which inspects memory.episodic for saveEntryWithSources, searchEntries, getEntrySources, applyReflection, getCursor, setCursor.","triggerScenarios":"Calling Memory.episodicMemory({ enabled: true }) (or any non-disabled config) on a Memory builder whose storage backend lacks the episodic methods, then triggering normalization.","commonSituations":"Custom persistent backend that implements threads/messages but not the .episodic namespace; enabling episodic memory against an older backend written before episodic support; mis-typed backend where memory.episodic is undefined.","solutions":["Use InMemoryMemory (default) which implements BuiltEpisodicMemoryStore.","Implement memory.episodic with all six required methods on your backend.","Drop .episodicMemory() if your backend cannot support it."],"exampleFix":"// before\nconst mem = new Memory().storage(customThreadsOnly).episodicMemory({});\n// after\nconst mem = new Memory().storage('memory').episodicMemory({});","handlingStrategy":"type-guard","validationCode":"import { hasEpisodicMemoryStore, isEpisodicMemoryEnabled } from '@n8n/agents/runtime/memory/episodic-memory';\n\nif (isEpisodicMemoryEnabled(config.episodicMemory) && !hasEpisodicMemoryStore(config.memory)) {\n  throw new Error('episodic memory needs a BuiltEpisodicMemoryStore backend');\n}","typeGuard":"import { hasEpisodicMemoryStore } from '@n8n/agents/runtime/memory/episodic-memory';\n\nfunction supportsEpisodicMemory(m: BuiltMemory): boolean {\n  return hasEpisodicMemoryStore(m);\n}","tryCatchPattern":null,"preventionTips":["Use the default InMemoryMemory for episodic memory unless persistence is required.","When shipping a custom backend, implement and test the full BuiltEpisodicMemoryStore surface."],"tags":["memory","episodic","storage","validation"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}