mem0ai/mem0 · error · Error
Databricks vector store: topK must be a positive integer, go
Error message
Databricks vector store: topK must be a positive integer, got ${topK} What it means
list() interpolates topK directly into the SQL LIMIT clause rather than binding it as a parameter, so it must be a positive safe integer. Number.isSafeInteger is used deliberately: huge values like 1e21 stringify as '1e+21' which is both invalid SQL and an injection-shaped hazard. Non-integers, zero, negatives, and unsafe integers all throw.
Source
Thrown at mem0-ts/src/oss/src/vector_stores/databricks.ts:724
}
}
await this.executeSql(`DROP TABLE IF EXISTS ${this.fullTableName}`);
}
async list(
filters?: SearchFilters,
topK: number = 100,
): Promise<[VectorStoreResult[], number]> {
// `limit` below is interpolated directly into the SQL string (not a bound parameter,
// and not passed through formatSqlValue()), so a non-integer or non-positive topK must
// be rejected here rather than reaching the query -- otherwise a caller that skips
// TypeScript's compile-time check (e.g. anything passing user input straight through)
// could inject arbitrary SQL via the LIMIT clause.
if (!Number.isSafeInteger(topK) || topK <= 0) {
// isSafeInteger (not isInteger): an unsafe/huge integer like 1e21 stringifies as "1e+21",
// which is meaningless as a LIMIT and would slip past a plain integer check.
throw new Error(
`Databricks vector store: topK must be a positive integer, got ${topK}`,
);
}
await this.initialize();
// Push the SQL-translatable conjunctive filters (session keys) into a WHERE
// clause so a filtered list does not pull the whole table to the client.
// filterVector below still enforces the complete filter, so this clause is a
// best-effort narrowing: untranslatable filters ($or/$not/metadata) yield an
// empty clause and fall back to a bounded scan (see LIMIT below) + local filtering.
const conjunctiveFilters = collectConjunctiveDatabricksFilters(filters);
const clauses = conjunctiveFilters.map(([key, value]) =>
buildStorageOptimizedDatabricksFilterClause(key, value),
);
const whereClause = clauses
.filter((clause): clause is string => Boolean(clause))
.join(" AND ");View on GitHub (pinned to 001c235229)
Solutions
- Validate and clamp topK before calling list(): reject or bound it to a sane range (e.g. 1-10000)
- Ensure the value is a Number, not a numeric string ('100' fails Number.isSafeInteger)
Example fix
// before const [rows, total] = await store.list(filters, req.query.limit as any); // after const raw = Number(req.query.limit); const topK = Number.isSafeInteger(raw) && raw > 0 ? Math.min(raw, 10000) : 100; const [rows, total] = await store.list(filters, topK);
Defensive patterns
Strategy: validation
Validate before calling
function safeTopK(raw: unknown, fallback = 100): number {
const n = Number(raw);
return Number.isSafeInteger(n) && n > 0 ? Math.min(n, 10000) : fallback;
} Type guard
const isSafeTopK = (v: unknown): v is number => typeof v === 'number' && Number.isSafeInteger(v) && v > 0;
Prevention
- Never pass raw query parameters as topK — validate and clamp first
- Use Number.isSafeInteger, not isInteger, when checking limits
When it happens
Trigger: Calling list(filters, topK) with topK = 0, -1, 1.5, Number.MAX_VALUE * 2, or user-supplied input like parseInt(req.query.limit) that yields NaN; also topK = 1e21 which passes plain isInteger but is not safe.
Common situations: Passing a raw query-string limit parameter through without validation; defaults computed as count*multiplier that overflow; iterating with dynamic page sizes that occasionally compute to 0.
Related errors
- Invalid ${label} '${name}': only letters, digits, and unders
- Invalid topK: ${topK}. Must be a non-negative integer.
- Invalid ${label} '${name}': only letters, digits, and unders
- Databricks vector store only accepts finite numbers.
- ${label} dimension mismatch. Expected ${this.dimension}, got
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/85cbb47c2d58134e.
Report an issue: GitHub.