n8n-io/n8n · error · Error
VectorStore "${this.name}" requires an embedding model — set
Error message
VectorStore "${this.name}" requires an embedding model — set it via .embeddingModel() What it means
Thrown by VectorStore.ensureBuilt() the first time you call search(), addDocuments(), or deleteDocuments(). The orchestrator needs an embedding model to convert text to/from vectors before it can talk to any backend, so it refuses to run without one. The message names the store and points at the missing builder call. Note the distinct sibling error for a missing backend (.store()).
Source
Thrown at packages/@n8n/agents/src/sdk/vector-store.ts:172
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;
}
}
function assertValidTopK(k: number): void {
if (!Number.isInteger(k) || k < 1) {
throw new Error(`topK must be an integer >= 1, got ${k}`);View on GitHub (pinned to 5ac6606e81)
Solutions
- Chain `.embeddingModel('openai/text-embedding-3-small')` (or another 'provider/model' string) onto the VectorStore before any search/add/delete call.
- If you already constructed an AI SDK EmbeddingModel, pass it directly: `.embeddingModel(myModel)`.
- Search your setup code for `new VectorStore(` and confirm every instance has both `.store(...)` and `.embeddingModel(...)` in the chain.
Example fix
// before
const store = new VectorStore('docs').store(new PgVectorStore('docs', opts));
await store.search('hello');
// after
const store = new VectorStore('docs')
.store(new PgVectorStore('docs', opts))
.embeddingModel('openai/text-embedding-3-small');
await store.search('hello'); Defensive patterns
Strategy: validation
Validate before calling
// Fail fast at construction time — both .store() and .embeddingModel() required.
function buildVectorStore(name: string, backend: BuiltVectorStoreBackend, model: string | EmbeddingModel): VectorStore {
const store = new VectorStore(name).store(backend).embeddingModel(model);
// Force ensureBuilt() eagerly so the error throws here, not deep in a request.
// (ensureBuilt is private; instead, do a no-op check by asserting the chain completed:)
return store;
}
// Or wrap your factory so callers can't forget the model:
function requireEmbeddingModel(store: VectorStore, model: string): VectorStore {
return store.embeddingModel(model);
} Type guard
// No type guard helps here — embeddingModelValue is private.
// Use a builder wrapper that makes the model a required argument:
function makeStore(name: string, opts: { backend: BuiltVectorStoreBackend; model: string }): VectorStore {
return new VectorStore(name).store(opts.backend).embeddingModel(opts.model);
} Try / catch
try {
await store.search('q');
} catch (err) {
if (err instanceof Error && /requires an embedding model/.test(err.message)) {
// configuration bug — surface to operator, do not retry
throw new Error(`Misconfigured vector store: ${err.message}`);
}
throw err;
} Prevention
- Treat .store() and .embeddingModel() as a required pair; lint your setup so a VectorStore is never constructed without both.
- Centralize VectorStore construction in one factory that takes backend + model as required arguments.
- In tests, add a smoke test that calls search() on a freshly built store to catch missing-model bugs early.
When it happens
Trigger: Calling `new VectorStore('docs').store(backend)` then immediately `await store.search('q')` or `store.addDocuments([...])` without an intervening `.embeddingModel(...)` call. Also fires when you build the VectorStore conditionally and the embeddingModel branch was skipped (e.g. an env-var guard returned early).
Common situations: Copy-pasting a store setup snippet and deleting the embeddingModel line; refactoring a factory function that returned the builder early; gating `.embeddingModel()` behind a feature flag that was off in the test env; wiring a backend first during local dev and forgetting the model.
Related errors
- Tool name is required
- Invalid filter operator "${operator}" for key "${key}". Supp
- filterableKeys must contain at least one key
- VectorStore "${this.name}" requires a description — set it v
- VectorStore "${this.name}" requires a backend — set it via .
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/f2a418e13dd55348.
Report an issue: GitHub.