n8n-io/n8n · error · Error
topK must be an integer >= 1, got ${k}
Error message
topK must be an integer >= 1, got ${k} What it means
Thrown by assertValidTopK() whenever a topK value is not a positive integer. Validation runs both eagerly in the .topK(k) builder and again on the per-call opts.topK passed to search(). The check is Number.isInteger(k) && k >= 1, so fractional numbers, zero, negatives, NaN, and Infinity all fail. This protects the underlying LIMIT/topK passed to each backend.
Source
Thrown at packages/@n8n/agents/src/sdk/vector-store.ts:190
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
- Pass a positive integer literal or a value you have clamped: `Math.max(1, Math.floor(value))`.
- If 0/'unset' must be supported in your config layer, translate it to the default (4) or omit the topK option entirely so the builder default applies.
- Validate external topK input with a guard before calling .topK() or search().
Example fix
// before
store.topK(0);
await store.search('q', { topK: 2.5 });
// after
store.topK(5);
await store.search('q', { topK: Math.max(1, Math.floor(config.limit)) }); Defensive patterns
Strategy: validation
Validate before calling
function safeTopK(value: unknown): number {
const n = typeof value === 'number' ? value : Number(value);
if (!Number.isInteger(n) || n < 1) {
throw new Error(`Invalid topK ${String(value)}: must be an integer >= 1`);
}
return n;
}
// Usage:
store.topK(safeTopK(config.limit));
await store.search('q', { topK: safeTopK(req.body.limit) }); Type guard
function isValidTopK(value: unknown): value is number {
return typeof value === 'number' && Number.isInteger(value) && value >= 1;
}
if (isValidTopK(input)) {
store.topK(input);
} Try / catch
if (opts?.topK !== undefined && (!Number.isInteger(opts.topK) || opts.topK < 1)) {
return res.status(400).json({ error: 'topK must be an integer >= 1' });
}
await store.search(query, opts); Prevention
- Coerce all external topK input through a single validator before passing it to .topK()/search().
- Treat config value 0/'unset' as 'use the default (4)' by omitting the option rather than passing 0.
- Type your API surface as number and add a runtime guard — TypeScript alone won't stop NaN or floats at runtime.
When it happens
Trigger: Calling `store.topK(0)`, `store.topK(2.5)`, `store.topK(-1)`, or `store.topK(NaN)`; calling `store.search('q', { topK: Math.round(score) })` where score rounds to 0; reading topK from user/config input parsed as a float; spreading a default of 0 that was meant as 'unset'.
Common situations: Config/UI slider that allows 0 as 'no limit'; JSON config with topK: 0 mistaken for 'use default'; arithmetic that produces a fractional result (e.g. count/2); coerced string input `Number('abc')` yielding NaN.
Related errors
- Invalid filter operator "${operator}" for key "${key}". Supp
- Filter operator "${operator}" on key "${key}" requires a non
- Filter operator "${operator}" on key "${key}" requires array
- Filter operator "${operator}" on key "${key}" requires a str
- filterableKeys must contain at least one key
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/088835352438186e.
Report an issue: GitHub.