{"record":{"id":"23e823784a10b2d0","repo":"mastra-ai/mastra","slug":"page-must-be-0-23e823","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/workflows/inmemory.ts","lineNumber":347,"sourceCode":"      return null;\n    }\n\n    const snapshot = typeof run.snapshot === 'string' ? JSON.parse(run.snapshot) : run.snapshot;\n    // Return a deep copy to prevent mutation\n    return snapshot ? cloneRunData(snapshot) : null;\n  }\n\n  async listWorkflowRuns({\n    workflowName,\n    fromDate,\n    toDate,\n    perPage,\n    page,\n    resourceId,\n    status,\n  }: StorageListWorkflowRunsInput = {}): Promise<WorkflowRuns> {\n    if (page !== undefined && page < 0) {\n      throw new Error('page must be >= 0');\n    }\n\n    let runs = Array.from(this.db.workflows.values());\n\n    if (workflowName) runs = runs.filter((run: any) => run.workflow_name === workflowName);\n    if (status) {\n      runs = runs.filter((run: any) => {\n        let snapshot: WorkflowRunState | string = run?.snapshot!;\n\n        if (!snapshot) {\n          return false;\n        }\n\n        if (typeof snapshot === 'string') {\n          try {\n            snapshot = JSON.parse(snapshot) as WorkflowRunState;\n          } catch {\n            return false;","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/domains/workflows/inmemory.ts#L329-L365","documentation":"`listWorkflowRuns` validates that `page`, when provided, is non-negative, throwing 'page must be >= 0'. Pages are zero-indexed; negative values indicate caller-side pagination bugs. Thrown before any filtering of runs occurs.","triggerScenarios":"Calling `listWorkflowRuns({ page: -1 })` or passing a page derived from `pageIndex - 1` when already at 0, or unvalidated negative user input flowing into the query.","commonSituations":"'Previous page' UI logic going below zero, negative sentinel values used to mean 'all runs', or arithmetic underflow in offset-to-page conversions.","solutions":["Clamp with `Math.max(0, page)` before calling.","Fix prev-page logic to stop at 0.","To fetch all runs, omit `page`/`perPage` or pass a large perPage instead of a negative page.","Validate pagination query params at the API boundary."],"exampleFix":"// before\nawait storage.listWorkflowRuns({ page: pageNum - 1 }); // pageNum could be 0\n// after\nawait storage.listWorkflowRuns({ page: Math.max(0, pageNum - 1) });","handlingStrategy":"validation","validationCode":"function toPage(page: unknown): number | undefined {\n  if (page === undefined) return undefined;\n  const n = typeof page === 'number' ? page : parseInt(String(page), 10);\n  return Number.isFinite(n) ? Math.max(0, Math.trunc(n)) : undefined;\n}\n// usage\nawait storage.listWorkflowRuns({ page: toPage(rawPage) });","typeGuard":"function isValidPage(page: unknown): page is number {\n  return typeof page === 'number' && Number.isInteger(page) && page >= 0;\n}","tryCatchPattern":"try {\n  return await storage.listWorkflowRuns({ page });\n} catch (err) {\n  if (err instanceof Error && err.message === 'page must be >= 0') {\n    return storage.listWorkflowRuns({ page: 0 });\n  }\n  throw err;\n}","preventionTips":["Clamp page to >= 0 at every pagination call site.","Fix prev-page logic so it never decrements below 0.","Validate pagination params at the HTTP boundary before storage calls."],"tags":["pagination","argument-validation","storage"],"backgroundTag":"pagination-negative-page","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}