{"record":{"id":"6f7877f37f0ed3fa","repo":"denoland/deno","slug":"limit-must-be-a-positive-integer-received-optio","errorCode":null,"errorMessage":"Limit must be a positive integer: received ${options.limit}","messagePattern":"Limit must be a positive integer: received (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/kv/01_db.ts","lineNumber":243,"sourceCode":"    );\n    if (!result) throw new TypeError(\"Failed to set value\");\n  }\n\n  list(\n    selector: Deno.KvListSelector,\n    options: {\n      limit?: number;\n      batchSize?: number;\n      cursor?: string;\n      reverse?: boolean;\n      consistency?: Deno.KvConsistencyLevel;\n    } = { __proto__: null },\n  ): KvListIterator {\n    if (\n      options.limit !== undefined &&\n      (!NumberIsInteger(options.limit) || options.limit <= 0)\n    ) {\n      throw new Error(\n        `Limit must be a positive integer: received ${options.limit}`,\n      );\n    }\n\n    let batchSize = options.batchSize ?? (options.limit ?? 100);\n    if (!NumberIsInteger(batchSize) || batchSize <= 0) {\n      throw new Error(\n        `batchSize must be a positive integer: received ${batchSize}`,\n      );\n    }\n    if (options.batchSize === undefined && batchSize > 500) batchSize = 500;\n\n    return new KvListIterator({\n      limit: options.limit,\n      selector,\n      cursor: options.cursor,\n      reverse: options.reverse ?? false,\n      consistency: options.consistency ?? \"strong\",","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/kv/01_db.ts#L225-L261","documentation":"Kv.list() validates its options synchronously before returning the iterator. `limit` must be a positive integer: 0, negative numbers, non-integers (1.5, NaN, Infinity) and non-number values all throw 'Limit must be a positive integer: received <value>'. Note that batchSize defaults to limit when batchSize is omitted, so an invalid limit is always reported at this check first.","triggerScenarios":"`kv.list(selector, { limit: 0 })`, `{ limit: -1 }`, `{ limit: 2.5 }`, `{ limit: NaN }`, `{ limit: \"100\" }`, or a limit computed from arithmetic that can reach 0 (e.g. Math.min(pageSize, remaining) when the last page is exactly consumed). `limit: undefined` is fine — the check is skipped.","commonSituations":"Paginating to the final page and computing remaining=0; limit read from an env var or config file arrives as a string; user-supplied page size passed through unvalidated; spread options where limit is 0 rather than omitted.","solutions":["Validate before calling: Number.isInteger(limit) && limit > 0.","Omit the limit key entirely when you want all matching entries.","Clamp computed limits: Math.max(1, Math.floor(remaining)).","Parse numeric config once at startup (Number(cfg.limit)) and fail fast there with a clear message."],"exampleFix":"// before\nconst it = kv.list({ prefix: [\"users\"] }, { limit: remaining }); // throws when remaining === 0\n\n// after\nconst opts = Number.isInteger(remaining) && remaining > 0 ? { limit: remaining } : {};\nconst it = kv.list({ prefix: [\"users\"] }, opts);","handlingStrategy":"validation","validationCode":"function listOptions(limit?: number, batchSize?: number) {\n  if (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {\n    throw new Error(`invalid limit: ${limit}`);\n  }\n  if (batchSize !== undefined && (!Number.isInteger(batchSize) || batchSize <= 0)) {\n    throw new Error(`invalid batchSize: ${batchSize}`);\n  }\n  return limit !== undefined ? { limit, ...(batchSize !== undefined ? { batchSize } : {}) } : {};\n}","typeGuard":"const isPositiveInt = (v: unknown): v is number =>\n  typeof v === \"number\" && Number.isInteger(v) && v > 0;","tryCatchPattern":null,"preventionTips":["Validate limits at the config boundary with Number.isInteger and > 0","Omit the limit key (undefined) rather than passing 0 for 'no limit'","Clamp computed limits with Math.max(1, Math.floor(x))"],"tags":["deno-kv","kv-list","pagination","limit","argument-validation"],"backgroundTag":"invalid-pagination-limit","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}