mastra-ai/mastra · error · HTTPException
page must be a non-negative integer
Error message
page must be a non-negative integer
What it means
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.
Source
Thrown at packages/server/src/server/handlers/workflows.ts:392
// If page/perPage provided, use directly; otherwise convert from limit/offset
let finalPage = page;
let finalPerPage = perPage;
if (finalPerPage === undefined && limit !== undefined) {
finalPerPage = limit;
}
if (finalPage === undefined && offset !== undefined && finalPerPage !== undefined && finalPerPage > 0) {
finalPage = Math.floor(offset / finalPerPage);
}
if (
finalPerPage !== undefined &&
(typeof finalPerPage !== 'number' || !Number.isInteger(finalPerPage) || finalPerPage <= 0)
) {
throw new HTTPException(400, { message: 'perPage must be a positive integer' });
}
if (finalPage !== undefined && (!Number.isInteger(finalPage) || finalPage < 0)) {
throw new HTTPException(400, { message: 'page must be a non-negative integer' });
}
const { workflow } = await listWorkflowsFromSystem({ mastra, workflowId });
if (!workflow) {
throw new HTTPException(404, { message: 'Workflow not found' });
}
const workflowRuns = (await workflow.listWorkflowRuns({
fromDate: fromDate ? (typeof fromDate === 'string' ? new Date(fromDate) : fromDate) : undefined,
toDate: toDate ? (typeof toDate === 'string' ? new Date(toDate) : toDate) : undefined,
perPage: finalPerPage,
page: finalPage,
resourceId: effectiveResourceId,
status,
})) || {
runs: [],
total: 0,
};
return workflowRuns;
} catch (error) {View on GitHub (pinned to 75dd419e61)
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
Example fix
// before const page = Math.ceil(total / perPage) - 1 - 1; // can go negative // after const page = Math.max(0, Math.floor(total / perPage) - 1);
Defensive patterns
Strategy: validation
Validate before calling
function sanitizePage(input) {
const n = typeof input === 'string' ? Number.parseInt(input, 10) : input;
if (!Number.isInteger(n) || n < 0) return 0;
return n;
} Type guard
function isNonNegativeInteger(v: unknown): v is number {
return typeof v === 'number' && Number.isInteger(v) && v >= 0;
} Try / catch
try {
return await workflow.listWorkflowRuns({ page });
} catch (e) {
if (e?.status === 400 && /page must be a non-negative integer/i.test(e?.message ?? '')) {
return await workflow.listWorkflowRuns({ page: 0 });
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- perPage must be a positive integer
- Workflow ID is required
- Run ID is required
- bad request: ${responseText}
- GitHub cursor must be a positive page number.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/755fbcbfce6d4779.
Report an issue: GitHub.