mastra-ai/mastra · error

page must be >= 0

Error message

page must be >= 0

What it means

validatePagination rejects a page argument that is negative, non-finite, or not a safe integer. Page numbers are 0-indexed in Mastra storage, so page must be an integer >= 0. This prevents undefined offset arithmetic in the storage layer.

Source

Thrown at packages/core/src/storage/domains/memory/base.ts:454

        );
      }

      // Also limit key length to prevent potential issues
      if (key.length > MAX_METADATA_KEY_LENGTH) {
        throw new Error(`Metadata key "${key}" exceeds maximum length of ${MAX_METADATA_KEY_LENGTH} characters.`);
      }
    }
  }

  /**
   * Validates pagination parameters and returns safe offset.
   * @param page - Page number (0-indexed)
   * @param perPage - Items per page (0 is allowed and returns empty results)
   * @throws Error if page is negative, perPage is negative/invalid, or offset would overflow
   */
  protected validatePagination(page: number, perPage: number): void {
    if (!Number.isFinite(page) || !Number.isSafeInteger(page) || page < 0) {
      throw new Error('page must be >= 0');
    }

    // perPage: 0 is allowed (returns empty results), negative values are rejected
    if (!Number.isFinite(perPage) || !Number.isSafeInteger(perPage) || perPage < 0) {
      throw new Error('perPage must be >= 0');
    }

    // Skip overflow check when perPage is 0 (no offset needed)
    if (perPage === 0) {
      return;
    }

    // Prevent overflow when calculating offset
    const offset = page * perPage;
    if (!Number.isSafeInteger(offset) || offset > Number.MAX_SAFE_INTEGER) {
      throw new Error('page value too large');
    }
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Clamp page to Math.max(0, Math.floor(Number(page))) before calling the storage API.
  2. Default page to 0 when the input is missing, NaN, or negative.
  3. Validate page with Number.isSafeInteger(page) && page >= 0 before the call.
  4. Fix 1-indexed UI code to subtract 1 before passing page to Mastra storage.

Example fix

// before
const { page = 1 } = req.query; // 1-indexed UI
await storage.listThreads({ page, perPage: 10 });
// after
const page = Math.max(0, Math.floor(Number(req.query.page ?? 1)) - 1);
await storage.listThreads({ page, perPage: 10 });
Defensive patterns

Strategy: validation

Validate before calling

function safePage(raw) {
  const n = Number(raw);
  return Number.isSafeInteger(n) && n >= 0 ? n : 0;
}

Type guard

function isValidPage(p: unknown): p is number {
  return typeof p === 'number' && Number.isSafeInteger(p) && p >= 0;
}

Try / catch

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

Prevention

When it happens

Trigger: Calling listThreads/listMessages with { page: -1 }, { page: NaN }, { page: 1.5 }, or { page: Infinity }; passing user-controlled pagination straight through without clamping.

Common situations: UI pagination math producing -1 when the user is on the first page and clicks 'previous'; parsing query params where '' or undefined coerces to NaN; off-by-one in 1-indexed vs 0-indexed page handling.

Related errors


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