{"record":{"id":"85cbb47c2d58134e","repo":"mem0ai/mem0","slug":"databricks-vector-store-topk-must-be-a-positive-i","errorCode":null,"errorMessage":"Databricks vector store: topK must be a positive integer, got ${topK}","messagePattern":"Databricks vector store: topK must be a positive integer, got (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/databricks.ts","lineNumber":724,"sourceCode":"      }\n    }\n\n    await this.executeSql(`DROP TABLE IF EXISTS ${this.fullTableName}`);\n  }\n\n  async list(\n    filters?: SearchFilters,\n    topK: number = 100,\n  ): Promise<[VectorStoreResult[], number]> {\n    // `limit` below is interpolated directly into the SQL string (not a bound parameter,\n    // and not passed through formatSqlValue()), so a non-integer or non-positive topK must\n    // be rejected here rather than reaching the query -- otherwise a caller that skips\n    // TypeScript's compile-time check (e.g. anything passing user input straight through)\n    // could inject arbitrary SQL via the LIMIT clause.\n    if (!Number.isSafeInteger(topK) || topK <= 0) {\n      // isSafeInteger (not isInteger): an unsafe/huge integer like 1e21 stringifies as \"1e+21\",\n      // which is meaningless as a LIMIT and would slip past a plain integer check.\n      throw new Error(\n        `Databricks vector store: topK must be a positive integer, got ${topK}`,\n      );\n    }\n\n    await this.initialize();\n\n    // Push the SQL-translatable conjunctive filters (session keys) into a WHERE\n    // clause so a filtered list does not pull the whole table to the client.\n    // filterVector below still enforces the complete filter, so this clause is a\n    // best-effort narrowing: untranslatable filters ($or/$not/metadata) yield an\n    // empty clause and fall back to a bounded scan (see LIMIT below) + local filtering.\n    const conjunctiveFilters = collectConjunctiveDatabricksFilters(filters);\n    const clauses = conjunctiveFilters.map(([key, value]) =>\n      buildStorageOptimizedDatabricksFilterClause(key, value),\n    );\n    const whereClause = clauses\n      .filter((clause): clause is string => Boolean(clause))\n      .join(\" AND \");","sourceCodeStart":706,"sourceCodeEnd":742,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/databricks.ts#L706-L742","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\nconst [rows, total] = await store.list(filters, req.query.limit as any);\n\n// after\nconst raw = Number(req.query.limit);\nconst topK = Number.isSafeInteger(raw) && raw > 0 ? Math.min(raw, 10000) : 100;\nconst [rows, total] = await store.list(filters, topK);","handlingStrategy":"validation","validationCode":"function safeTopK(raw: unknown, fallback = 100): number {\n  const n = Number(raw);\n  return Number.isSafeInteger(n) && n > 0 ? Math.min(n, 10000) : fallback;\n}","typeGuard":"const isSafeTopK = (v: unknown): v is number => typeof v === 'number' && Number.isSafeInteger(v) && v > 0;","tryCatchPattern":null,"preventionTips":["Never pass raw query parameters as topK — validate and clamp first","Use Number.isSafeInteger, not isInteger, when checking limits"],"tags":["databricks","sql-injection","validation","pagination","typescript"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}