mastra-ai/mastra · error

page must be 0 when perPage is false

Error message

page must be 0 when perPage is false

What it means

When perPage is false (fetch-all mode), only page 0 is valid because there is a single unpaginated result set. Passing any other page with perPage: false throws 'page must be 0 when perPage is false'.

Source

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

   * @throws Error if perPageInput is false and page !== 0
   * @throws Error if perPageInput is invalid (not false or a non-negative safe integer)
   * @throws Error if page is invalid or offset would overflow
   */
  protected validatePaginationInput(page: number, perPageInput: number | false): void {
    // Validate perPageInput type first
    if (perPageInput !== false) {
      if (typeof perPageInput !== 'number' || !Number.isFinite(perPageInput) || !Number.isSafeInteger(perPageInput)) {
        throw new Error('perPage must be false or a safe integer');
      }
      if (perPageInput < 0) {
        throw new Error('perPage must be >= 0');
      }
    }

    // When fetching all (perPage: false), only page 0 is valid
    if (perPageInput === false) {
      if (page !== 0) {
        throw new Error('page must be 0 when perPage is false');
      }
      // Still validate page is a valid integer
      if (!Number.isFinite(page) || !Number.isSafeInteger(page)) {
        throw new Error('page must be >= 0');
      }
      return;
    }

    // For numeric perPage, delegate to existing validation
    this.validatePagination(page, perPageInput);
  }
}

const THREAD_ORDER_BY_SET: Record<ThreadOrderBy, true> = {
  createdAt: true,
  updatedAt: true,
};

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Force page to 0 whenever perPage is false.
  2. Reset the pagination state when switching to fetch-all mode.
  3. Conditionally build the params object: perPage === false ? { page: 0, perPage: false } : { page, perPage }.
  4. Ignore/skip the page parameter in fetch-all code paths.

Example fix

// before
await storage.listThreads({ page: currentPage, perPage: false });
// after
await storage.listThreads({ page: 0, perPage: false });
Defensive patterns

Strategy: validation

Validate before calling

const params = perPage === false
  ? { page: 0, perPage: false }
  : { page, perPage };

Type guard

function validListParams(p: { page: number; perPage: number | false }) {
  return p.perPage === false ? { ...p, page: 0 } : p;
}

Try / catch

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

Prevention

When it happens

Trigger: Calling listThreads/listMessages with { page: 2, perPage: false }; combining 'fetch all' with UI pagination state that is already on page N.

Common situations: Export-all feature reusing paginated request state; toggling perPage to false without resetting the page counter; generic request-mapping code that always forwards page.

Related errors


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