n8n-io/n8n · error · Error
Observational memory requires a storage backend that impleme
Error message
Observational memory requires a storage backend that implements BuiltObservationLogStore.
What it means
Thrown from resolveMemoryConfigDefaults when observationalMemory is enabled but the configured storage backend (config.memory) does not implement BuiltObservationLogStore. The store capability is detected structurally via hasObservationLogStore, which checks for the six observation-log methods (appendObservationLogEntries, getActiveObservationLog, getObservationLog, dropObservationLogEntries, supersedeObservationLogEntries, applyObservationLogReflection).
Source
Thrown at packages/@n8n/agents/src/sdk/memory.ts:103
}
export function resolveMemoryConfigDefaults(
config: MemoryConfig,
options: ResolveMemoryConfigDefaultsOptions,
): MemoryConfig {
const episodicMemory = isEpisodicMemoryEnabled(config.episodicMemory)
? resolveEpisodicMemoryConfig(config.episodicMemory, options)
: config.episodicMemory;
if (!config.observationalMemory) {
return normalizeMemoryConfig({
...config,
episodicMemory,
});
}
if (!hasObservationLogStore(config.memory)) {
throw new Error(
'Observational memory requires a storage backend that implements BuiltObservationLogStore.',
);
}
const observationalMemoryConfig =
config.observationLog?.renderTokenBudget !== undefined &&
config.observationalMemory.renderTokenBudget === undefined
? {
...config.observationalMemory,
renderTokenBudget: config.observationLog.renderTokenBudget,
}
: config.observationalMemory;
const observationalMemory = resolveObservationalMemoryConfig(observationalMemoryConfig, options);
return normalizeMemoryConfig({
...config,
memory: config.memory,
observationalMemory,View on GitHub (pinned to 5ac6606e81)
Solutions
- Use the default InMemoryMemory (omit .storage() or pass 'memory') — it implements both BuiltObservationLogStore and BuiltEpisodicMemoryStore.
- Extend your custom backend to implement all six BuiltObservationLogStore methods (and the task-lock methods when needed).
- If your backend cannot support observational memory, do not call .observationalMemory() on that agent's Memory builder.
Example fix
// before
const mem = new Memory().storage(customBackend).observationalMemory({});
// after
const mem = new Memory().storage('memory').observationalMemory({}); Defensive patterns
Strategy: type-guard
Validate before calling
import { hasObservationLogStore } from '@n8n/agents/runtime/memory/observation-log-store';
if (config.observationalMemory && !hasObservationLogStore(config.memory)) {
throw new Error('observational memory needs a BuiltObservationLogStore backend');
} Type guard
import { hasObservationLogStore } from '@n8n/agents/runtime/memory/observation-log-store';
function supportsObservationalMemory(m: BuiltMemory): boolean {
return hasObservationLogStore(m);
} Prevention
- Default to .storage('memory') unless you have a specific reason to bring a custom backend.
- If you implement a custom backend, have it declare which Built*Store interfaces it implements and unit-test for them.
When it happens
Trigger: Passing a custom BuiltMemory to Memory.storage(customBackend), enabling .observationalMemory({...}), then triggering resolveMemoryConfigDefaults (typically through Agent build) — and the custom backend omits any of the observation-log methods.
Common situations: Bringing your own persistent backend that only implements thread/message storage; partial implementation of BuiltMemory; upgrading @n8n/agents where observational memory was added later than your backend was written.
Related errors
- Episodic memory requires a storage backend that implements B
- Cannot decrease maxIterations when resuming a run. Expected
- Run ${this.runId} is not suspended. Cannot resume.
- Checkpoint for runId ${this.runId} has pending tool calls —
- Model ID is required
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/0d1e475fd36ba572.
Report an issue: GitHub.