n8n-io/n8n · error · Error
VectorStore "${this.name}" requires a description — set it v
Error message
VectorStore "${this.name}" requires a description — set it via .description() or asTool({ description }) What it means
VectorStore.asTool() exposes the store as an agent tool, and the tool description is what the LLM uses to decide when to call it. If neither asTool({ description }) nor a prior .description() on the store set one, the build fails — a tool without a description would be invisible or misused by the model.
Source
Thrown at packages/@n8n/agents/src/sdk/vector-store.ts:134
/** Delete documents from the store by id. */
async deleteDocuments(ids: string[]): Promise<void> {
if (ids.length === 0) return;
const { backend } = this.ensureBuilt();
await backend.delete({ ids });
}
/**
* Expose this store as an agent tool. Pass `filterableKeys` (metadata key
* -> description) to also let the model narrow results with a filter.
*/
asTool(opts?: {
name?: string;
description?: string;
filterableKeys?: Record<string, string>;
}): Tool {
const description = opts?.description ?? this.descriptionValue;
if (!description) {
throw new Error(
`VectorStore "${this.name}" requires a description — set it via .description() or asTool({ description })`,
);
}
const toolName = opts?.name ?? sanitizeToolName(`search_${this.name}`);
if (!opts?.filterableKeys) {
return new Tool(toolName)
.description(description)
.input(z.object({ query: z.string().describe('Natural language search query') }))
.handler(async ({ query }) => ({ results: await this.search(query) }));
}
const filterSchema = buildFilterInputSchema(opts.filterableKeys);
return new Tool(toolName)
.description(description)
.input(
z.object({View on GitHub (pinned to 5ac6606e81)
Solutions
- Call .description('Search the docs for...') on the VectorStore before .asTool().
- Or pass it inline: store.asTool({ description: 'Search the docs for...' }).
- Write LLM-facing descriptions: state what the store contains, when to use it, and what queries work best.
Example fix
// before — throws
const store = new VectorStore('docs').store(backend).embeddingModel('openai/...');
agent.tool(store.asTool());
// after — set description
const store = new VectorStore('docs')
.description('Search internal product docs by semantic similarity')
.store(backend)
.embeddingModel('openai/...');
agent.tool(store.asTool()); Defensive patterns
Strategy: validation
Validate before calling
function asSearchTool(store: VectorStore, desc?: string) {
if (!desc || desc.trim().length === 0) {
throw new Error('VectorStore tool requires an LLM-facing description');
}
return store.asTool({ description: desc });
} Type guard
function hasDescription(desc: unknown): desc is string {
return typeof desc === 'string' && desc.trim().length > 0;
} Prevention
- Set .description() on the VectorStore at construction time so asTool() always has one.
- Write tool descriptions aimed at the LLM: what the store contains, when to search it, what queries work.
- Centralize tool registration in a factory that requires a description argument.
When it happens
Trigger: Calling new VectorStore('docs').asTool() without first calling .description('...') on the store and without passing description in the asTool options. Also hit when description is conditionally set but the condition was false.
Common situations: Building a store programmatically and forgetting the description; assuming the store's name doubles as the tool description; refactoring that moves .description() out of the chain.
Related errors
- filterableKeys must contain at least one key
- Invalid filter operator "${operator}" for key "${key}". Supp
- VectorStore "${this.name}" requires a backend — set it via .
- Azure AI Search endpoint is missing or invalid
- Model ID is required
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/d18b8e87d8f5395b.
Report an issue: GitHub.