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

  1. Use the default InMemoryMemory (omit .storage() or pass 'memory') — it implements both BuiltObservationLogStore and BuiltEpisodicMemoryStore.
  2. Extend your custom backend to implement all six BuiltObservationLogStore methods (and the task-lock methods when needed).
  3. 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

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


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/0d1e475fd36ba572. Report an issue: GitHub.