mastra-ai/mastra · error

page must be >= 0

Error message

page must be >= 0

What it means

The in-memory MCP servers storage adapter validates pagination arguments in list(). A negative page index is rejected because page offsets cannot be below zero. This is an eager argument-validation guard so bad pagination input fails fast instead of producing an invalid slice.

Source

Thrown at packages/core/src/storage/domains/mcp-servers/inmemory.ts:126

    return this.deepCopyConfig(updatedConfig);
  }

  async delete(id: string): Promise<void> {
    // Idempotent delete
    this.db.mcpServers.delete(id);
    // Also delete all versions for this server
    await this.deleteVersionsByParentId(id);
  }

  async list(args?: StorageListMCPServersInput): Promise<StorageListMCPServersOutput> {
    const { page = 0, perPage: perPageInput, orderBy, authorId, metadata, status = 'published' } = 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 MCP servers and apply filters
    let configs = Array.from(this.db.mcpServers.values());

    // Filter by status
    if (status) {
      configs = configs.filter(config => config.status === status);
    }

    // Filter by authorId if provided
    if (authorId !== undefined) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass a page value >= 0 (first page is 0)
  2. Clamp/validate page before calling, e.g. Math.max(0, Number(page) || 0)
  3. Sanitize incoming query parameters with a schema (zod etc.) at the API boundary

Example fix

// before
await storage.listMCPServers({ page: -1 });
// after
const page = Math.max(0, Number(input.page ?? 0));
await storage.listMCPServers({ page });
Defensive patterns

Strategy: validation

Validate before calling

function assertPage(page: unknown): number {
  const n = Number(page ?? 0);
  if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) throw new RangeError(`page must be a non-negative integer, got ${page}`);
  return n;
}

Type guard

const isValidPage = (p: unknown): p is number => typeof p === 'number' && Number.isInteger(p) && p >= 0;

Try / catch

try {
  return await storage.listMCPServers({ page });
} catch (e) {
  if (e instanceof Error && e.message === 'page must be >= 0') {
    return storage.listMCPServers({ page: 0 });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the mcpServers domain list() (listMCPServers) with page < 0, e.g. page: -1, typically from an unvalidated API query parameter or a page counter decremented below zero.

Common situations: Server routes passing req.query.page directly without clamping; client-side 'load previous page' logic that goes below page 0; off-by-one in loop-driven pagination.

Related errors


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