n8n-io/n8n · error · Error

VectorStore "${this.name}" requires a backend — set it via .

Error message

VectorStore "${this.name}" requires a backend — set it via .store()

What it means

VectorStore.ensureBuilt() is the lazy-build gate called by search() and addDocuments() before any embedding or backend operation. It requires a backend set via .store(backend); without one there is nothing to query or upsert against. The check fires before the embedding-model check, so backend is the first missing-prerequisite surfaced.

Source

Thrown at packages/@n8n/agents/src/sdk/vector-store.ts:169

			.input(
				z.object({
					query: z.string().describe('Natural language search query'),
					filter: filterSchema,
				}),
			)
			.handler(async ({ query, filter }) => ({
				results: await this.search(
					query,
					filter && filter.length > 0
						? { filter: { conditions: filter, combineWith: 'and' } }
						: undefined,
				),
			}));
	}

	private ensureBuilt(): { backend: BuiltVectorStoreBackend; embeddingModel: EmbeddingModel } {
		if (!this.backend) {
			throw new Error(`VectorStore "${this.name}" requires a backend — set it via .store()`);
		}
		if (!this.embeddingModelValue) {
			throw new Error(
				`VectorStore "${this.name}" requires an embedding model — set it via .embeddingModel()`,
			);
		}
		return { backend: this.backend, embeddingModel: this.embeddingModelValue };
	}

	/** Normalizes and validates a filter; returns `undefined` for an empty one so it's never a no-op `WHERE`. */
	private resolveFilter(input?: VectorFilterInput): VectorFilter | undefined {
		if (input === undefined) return undefined;
		const normalized = normalizeFilterInput(input);
		assertValidFilter(normalized);
		return normalized.conditions.length > 0 ? normalized : undefined;
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Call .store(backend) with a BuiltVectorStoreBackend instance (e.g. new PgVectorStore(...)) before search/addDocuments.
  2. Ensure the backend variable is defined before passing it to .store() — log or assert it during async init.
  3. If using the store as a tool, .store() must still be called before the agent first invokes the tool.

Example fix

// before — throws on first search
const store = new VectorStore('docs').embeddingModel('openai/text-embedding-3-small');
await store.search('query');

// after
const backend = new PgVectorStore({ ... });
const store = new VectorStore('docs')
  .store(backend)
  .embeddingModel('openai/text-embedding-3-small');
await store.search('query');
Defensive patterns

Strategy: validation

Validate before calling

function readyStore(name: string, backend: unknown, model: string) {
  if (!backend) throw new Error('VectorStore requires a backend instance');
  return new VectorStore(name).store(backend as any).embeddingModel(model);
}

Type guard

function isVectorStoreBackend(value: unknown): boolean {
  return value !== null && typeof value === 'object' && value !== undefined &&
    typeof (value as any).query === 'function' &&
    typeof (value as any).upsert === 'function';
}

Prevention

When it happens

Trigger: Calling new VectorStore('docs').embeddingModel('openai/...').search('q') (or .addDocuments(...)) without chaining .store(backend). Also triggered when .store() was called with undefined due to an uninitialized backend variable.

Common situations: Prototyping a store and forgetting the backend; conditionally constructing the backend (e.g. only in production) but running the store in a test env; refactoring that moves .store() out of the chain; backend variable that resolved to undefined after an async init that hadn't completed.

Related errors


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