{"record":{"id":"e45ff949c3db4910","repo":"mastra-ai/mastra","slug":"page-must-be-0-e45ff9","errorCode":null,"errorMessage":"page must be >= 0","messagePattern":"page must be >= 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/domains/memory/base.ts","lineNumber":454,"sourceCode":"        );\n      }\n\n      // Also limit key length to prevent potential issues\n      if (key.length > MAX_METADATA_KEY_LENGTH) {\n        throw new Error(`Metadata key \"${key}\" exceeds maximum length of ${MAX_METADATA_KEY_LENGTH} characters.`);\n      }\n    }\n  }\n\n  /**\n   * Validates pagination parameters and returns safe offset.\n   * @param page - Page number (0-indexed)\n   * @param perPage - Items per page (0 is allowed and returns empty results)\n   * @throws Error if page is negative, perPage is negative/invalid, or offset would overflow\n   */\n  protected validatePagination(page: number, perPage: number): void {\n    if (!Number.isFinite(page) || !Number.isSafeInteger(page) || page < 0) {\n      throw new Error('page must be >= 0');\n    }\n\n    // perPage: 0 is allowed (returns empty results), negative values are rejected\n    if (!Number.isFinite(perPage) || !Number.isSafeInteger(perPage) || perPage < 0) {\n      throw new Error('perPage must be >= 0');\n    }\n\n    // Skip overflow check when perPage is 0 (no offset needed)\n    if (perPage === 0) {\n      return;\n    }\n\n    // Prevent overflow when calculating offset\n    const offset = page * perPage;\n    if (!Number.isSafeInteger(offset) || offset > Number.MAX_SAFE_INTEGER) {\n      throw new Error('page value too large');\n    }\n  }","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/domains/memory/base.ts#L436-L472","documentation":"validatePagination rejects a page argument that is negative, non-finite, or not a safe integer. Page numbers are 0-indexed in Mastra storage, so page must be an integer >= 0. This prevents undefined offset arithmetic in the storage layer.","triggerScenarios":"Calling listThreads/listMessages with { page: -1 }, { page: NaN }, { page: 1.5 }, or { page: Infinity }; passing user-controlled pagination straight through without clamping.","commonSituations":"UI pagination math producing -1 when the user is on the first page and clicks 'previous'; parsing query params where '' or undefined coerces to NaN; off-by-one in 1-indexed vs 0-indexed page handling.","solutions":["Clamp page to Math.max(0, Math.floor(Number(page))) before calling the storage API.","Default page to 0 when the input is missing, NaN, or negative.","Validate page with Number.isSafeInteger(page) && page >= 0 before the call.","Fix 1-indexed UI code to subtract 1 before passing page to Mastra storage."],"exampleFix":"// before\nconst { page = 1 } = req.query; // 1-indexed UI\nawait storage.listThreads({ page, perPage: 10 });\n// after\nconst page = Math.max(0, Math.floor(Number(req.query.page ?? 1)) - 1);\nawait storage.listThreads({ page, perPage: 10 });","handlingStrategy":"validation","validationCode":"function safePage(raw) {\n  const n = Number(raw);\n  return Number.isSafeInteger(n) && n >= 0 ? n : 0;\n}","typeGuard":"function isValidPage(p: unknown): p is number {\n  return typeof p === 'number' && Number.isSafeInteger(p) && p >= 0;\n}","tryCatchPattern":"try {\n  await storage.listThreads({ page: safePage(rawPage), perPage });\n} catch (e) {\n  if (e instanceof Error && e.message === 'page must be >= 0') {\n    return storage.listThreads({ page: 0, perPage });\n  }\n  throw e;\n}","preventionTips":["Always clamp user-supplied page values","Remember pages are 0-indexed in Mastra storage","Never pass raw query strings as page"],"tags":["validation","pagination","storage"],"backgroundTag":"invalid-pagination-parameters","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}