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

  1. Call .description('Search the docs for...') on the VectorStore before .asTool().
  2. Or pass it inline: store.asTool({ description: 'Search the docs for...' }).
  3. 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

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


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