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

  1. Validate and clamp topK before calling list(): reject or bound it to a sane range (e.g. 1-10000)
  2. 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

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


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/85cbb47c2d58134e. Report an issue: GitHub.