{"record":{"id":"755fbcbfce6d4779","repo":"mastra-ai/mastra","slug":"page-must-be-a-non-negative-integer","errorCode":null,"errorMessage":"page must be a non-negative integer","messagePattern":"page must be a non-negative integer","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/workflows.ts","lineNumber":392,"sourceCode":"      // If page/perPage provided, use directly; otherwise convert from limit/offset\n      let finalPage = page;\n      let finalPerPage = perPage;\n\n      if (finalPerPage === undefined && limit !== undefined) {\n        finalPerPage = limit;\n      }\n      if (finalPage === undefined && offset !== undefined && finalPerPage !== undefined && finalPerPage > 0) {\n        finalPage = Math.floor(offset / finalPerPage);\n      }\n\n      if (\n        finalPerPage !== undefined &&\n        (typeof finalPerPage !== 'number' || !Number.isInteger(finalPerPage) || finalPerPage <= 0)\n      ) {\n        throw new HTTPException(400, { message: 'perPage must be a positive integer' });\n      }\n      if (finalPage !== undefined && (!Number.isInteger(finalPage) || finalPage < 0)) {\n        throw new HTTPException(400, { message: 'page must be a non-negative integer' });\n      }\n      const { workflow } = await listWorkflowsFromSystem({ mastra, workflowId });\n      if (!workflow) {\n        throw new HTTPException(404, { message: 'Workflow not found' });\n      }\n      const workflowRuns = (await workflow.listWorkflowRuns({\n        fromDate: fromDate ? (typeof fromDate === 'string' ? new Date(fromDate) : fromDate) : undefined,\n        toDate: toDate ? (typeof toDate === 'string' ? new Date(toDate) : toDate) : undefined,\n        perPage: finalPerPage,\n        page: finalPage,\n        resourceId: effectiveResourceId,\n        status,\n      })) || {\n        runs: [],\n        total: 0,\n      };\n      return workflowRuns;\n    } catch (error) {","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workflows.ts#L374-L410","documentation":"The workflow-runs route validates `page` and throws 400 'page must be a non-negative integer' when page is provided but is negative or not an integer. Zero is allowed (first page); -1, 1.5, or a non-numeric string are rejected. This check runs after the perPage validation and before the runs are fetched from storage.","triggerScenarios":"GET /api/workflows/:id/runs?page=-1; computing page as currentPage-1 when already on page 0 (yielding -1); passing a float from custom pagination math; sending page as an unparsed string.","commonSituations":"Client-side 'previous page' buttons not clamped at 0; fractional pages from dividing total items by perPage and passing the raw quotient; string query params forwarded without parsing.","solutions":["Clamp page to >= 0 with Math.max(0, page) before requesting","Use Math.floor/Math.round on computed page values","Parse string query params with Number.parseInt before sending","Omit page to get the default first page"],"exampleFix":"// before\nconst page = Math.ceil(total / perPage) - 1 - 1; // can go negative\n// after\nconst page = Math.max(0, Math.floor(total / perPage) - 1);","handlingStrategy":"validation","validationCode":"function sanitizePage(input) {\n  const n = typeof input === 'string' ? Number.parseInt(input, 10) : input;\n  if (!Number.isInteger(n) || n < 0) return 0;\n  return n;\n}","typeGuard":"function isNonNegativeInteger(v: unknown): v is number {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 0;\n}","tryCatchPattern":"try {\n  return await workflow.listWorkflowRuns({ page });\n} catch (e) {\n  if (e?.status === 400 && /page must be a non-negative integer/i.test(e?.message ?? '')) {\n    return await workflow.listWorkflowRuns({ page: 0 });\n  }\n  throw e;\n}","preventionTips":["Clamp computed pages: Math.max(0, Math.floor(page))","Guard 'previous page' UI actions so page never goes below 0","Parse string params with Number.parseInt before sending","Centralize pagination math in one tested utility"],"tags":["http-400","workflows","pagination","validation","server-api"],"backgroundTag":"invalid-pagination-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}