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

  1. Clamp the computed page to 0 before calling list: Math.max(0, requestedPage)
  2. If the caller means 'return everything', pass perPage: false instead of manipulating page
  3. Fix pagination UI logic so 'previous' is disabled on page 0
  4. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/b81352b746dec1fb. Report an issue: GitHub.