phacility/phabricator · error · Exception

Maximum page size for Conduit API method calls is 100, but t

Error message

Maximum page size for Conduit API method calls is 100, but this call specified %s.

What it means

setPagerSizeForConduit() caps 'limit' for generated Conduit search methods at 100 results per page (it also silently treats >= 0xFFFF pagesize as 'unlimited internal query'). Requesting limit > 100 throws immediately instead of running a query the caller cannot rely on. Pagination beyond 100 uses 'after' cursors, not bigger limits.

Source

Thrown at src/applications/search/engine/PhabricatorApplicationSearchEngine.php:1381

  }

  private function setPagerLimitForConduit($pager, ConduitAPIRequest $request) {
    $limit = $request->getValue('limit');

    // If there's no limit specified and the query uses a weird huge page
    // size, just leave it at the default gigantic page size. Otherwise,
    // make sure it's between 1 and 100, inclusive.

    if ($limit === null) {
      if ($pager->getPageSize() >= 0xFFFF) {
        return;
      } else {
        $limit = 100;
      }
    }

    if ($limit > 100) {
      throw new Exception(
        pht(
          'Maximum page size for Conduit API method calls is 100, but '.
          'this call specified %s.',
          $limit));
    }

    if ($limit < 1) {
      throw new Exception(
        pht(
          'Minimum page size for API searches is 1, but this call '.
          'specified %s.',
          $limit));
    }

    $pager->setPageSize($limit);
  }

  private function setPagerOffsetsForConduit(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Set limit <= 100 (e.g. 100) and paginate with the 'after' cursor returned in the response until 'cursor.after' is null.
  2. For full exports, loop: fetch 100, pass response cursor.after as request after, repeat; respect rate/sleep between pages.
  3. If you genuinely need everything server-side, use a dedicated export/reporting path rather than Conduit search pagination.
  4. Do not attempt to raise the cap - it is a hard API contract in the engine.

Example fix

// before
$after = null;
do {
  $r = conduit('maniphest.search', array('limit' => 1000));
  ...
} while (false);

// after
$after = null;
do {
  $r = conduit('maniphest.search', array('limit' => 100, 'after' => $after));
  $after = idxv($r, array('cursor', 'after'));
} while ($after);
Defensive patterns

Strategy: validation

Validate before calling

$params['limit'] = max(1, min(100, (int)$requested_limit));

Type guard

function isValidConduitLimit($n) { return is_int($n) && $n >= 1 && $n <= 100; }

Try / catch

try {
  $page = $client->call('maniphest.search', $params);
} catch (Exception $ex) {
  if (strpos($ex->getMessage(), 'Maximum page size') !== false) {
    $params['limit'] = 100;
    $page = $client->call('maniphest.search', $params);
  }
}

Prevention

When it happens

Trigger: Calling `<app>.search` with `"limit": 500` (or any value 101+); also custom code invoking buildQueryFromRequest on an engine with a large limit parameter. Default when limit is null is 100 unless the pager already carries the giant internal page size.

Common situations: Scripts ported from the old `<app>.query` methods that pulled hundreds of rows in one call; users trying to export all tasks at once; integrations sizing limit from a config constant that drifted above 100.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/d65108b1f29ab875. Report an issue: GitHub.