mastra-ai/mastra · error
page must be >= 0
Error message
page must be >= 0
What it means
Input validation in list(): the page argument must be a non-negative integer offset page index. Negative pages have no meaning for slice-based pagination, so the in-memory workspace domain rejects them explicitly instead of returning empty or wrapping around results.
Source
Thrown at packages/core/src/storage/domains/workspaces/inmemory.ts:203
return this.deepCopyConfig(updatedConfig);
}
async delete(id: string): Promise<void> {
// Idempotent delete
this.db.workspaces.delete(id);
// Also delete all versions for this workspace
await this.deleteVersionsByParentId(id);
}
async list(args?: StorageListWorkspacesInput): Promise<StorageListWorkspacesOutput> {
const { page = 0, perPage: perPageInput, orderBy, authorId, metadata } = args || {};
const { field, direction } = this.parseOrderBy(orderBy);
// Normalize perPage for query (false → MAX_SAFE_INTEGER, 0 → 0, undefined → 100)
const perPage = normalizePerPage(perPageInput, 100);
if (page < 0) {
throw new Error('page must be >= 0');
}
// Prevent unreasonably large page values
const maxOffset = Number.MAX_SAFE_INTEGER / 2;
if (page * perPage > maxOffset) {
throw new Error('page value too large');
}
// Get all workspaces and apply filters
let configs = Array.from(this.db.workspaces.values());
// Filter by authorId if provided
if (authorId !== undefined) {
configs = configs.filter(config => config.authorId === authorId);
}
// Filter by metadata if provided (AND logic)
if (metadata && Object.keys(metadata).length > 0) {View on GitHub (pinned to 75dd419e61)
Solutions
- Clamp the computed page to 0 before calling list: Math.max(0, requestedPage)
- If the caller means 'return everything', pass perPage: false instead of manipulating page
- Fix pagination UI logic so 'previous' is disabled on page 0
- Validate page inputs at API boundaries before forwarding to storage
Example fix
// before
const res = await storage.workspaces.list({ page: currentPage - 1 });
// after
const page = Math.max(0, currentPage - 1);
const res = await storage.workspaces.list({ page }); Defensive patterns
Strategy: validation
Validate before calling
function toSafePage(page: number): number {
if (!Number.isInteger(page) || page < 0) throw new RangeError(`page must be a non-negative integer, got ${page}`);
return page;
} Type guard
function isValidPage(page: unknown): page is number {
return typeof page === 'number' && Number.isInteger(page) && page >= 0;
} Try / catch
try {
return await storage.workspaces.list({ page, perPage });
} catch (err) {
if (err instanceof Error && /page must be >= 0|page value too large/.test(err.message)) {
return { workspaces: [], total: 0, page: 0, perPage, hasMore: false };
}
throw err;
} Prevention
- Clamp page with Math.max(0, page) at the data-access boundary
- Disable 'previous' pagination controls at page 0
- Sanitize/coerce external page params (query strings, API payloads)
- Use perPage: false for fetch-all instead of extreme page tricks
When it happens
Trigger: Calling storage.workspaces.list({ page: -1 }) or any negative number; passing an uninitialized/NaN-ish variable that ends up negative; off-by-one decrements when computing the previous page (page - 1 when page is already 0 minus more).
Common situations: Cursor/pagination UI state going negative when a user is on page 0 and clicks 'previous'; client-side code defaulting page to -1 to mean 'unset'; tests passing sentinel negative values.
Related errors
- page value too large
- perPage must be >= 0
- page must be >= 0
- page value too large
- Invalid knowledge node cursor.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/b81352b746dec1fb.
Report an issue: GitHub.