phacility/phabricator · error · Exception

Expected a query key or a set of query constraints.

Error message

Expected a query key or a set of query constraints.

What it means

PhabricatorBulkEngine's bulk-edit flow needs either a saved query key or passthrough request data carrying query constraints. With neither, it refuses to run rather than execute an unconstrained query that could match every object in the install and time out. This is a deliberate guard inherited from a TODO about huge result sets.

Source

Thrown at src/applications/transactions/bulk/PhabricatorBulkEngine.php:174

    if ($query_key !== null && strlen($query_key)) {
      if ($search_engine->isBuiltinQuery($query_key)) {
        $saved = $search_engine->buildSavedQueryFromBuiltin($query_key);
      } else {
        $saved = id(new PhabricatorSavedQueryQuery())
          ->setViewer($viewer)
          ->withQueryKeys(array($query_key))
          ->executeOne();
        if (!$saved) {
          return new Aphront404Response();
        }
      }
    } else {
      // TODO: For now, since we don't deal gracefully with queries which
      // match a huge result set, just bail if we don't have any query
      // parameters instead of querying for a trillion tasks and timing out.
      $request_data = $request->getPassthroughRequestData();
      if (!$request_data) {
        throw new Exception(
          pht(
            'Expected a query key or a set of query constraints.'));
      }

      $saved = $search_engine->buildSavedQueryFromRequest($request);
      $search_engine->saveQuery($saved);
    }

    $object_query = $search_engine->buildQueryFromSavedQuery($saved)
      ->setViewer($viewer);
    $object_list = $object_query->execute();
    $object_list = mpull($object_list, null, 'getPHID');

    // If the user has submitted the bulk edit form, select only the objects
    // they checked.
    if ($request->getBool('bulkEngine')) {
      $target_phids = $request->getArr('bulkTargetPHIDs');

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Enter bulk edit from a saved/engine search results page so the query key is carried in the URI
  2. If building a custom flow, POST the search constraints as passthrough request data or pass a saved query key explicitly
  3. Verify the search engine actually parsed and stored the constraints you intended

Example fix

// before: linking straight to the bulk flow
return id(new AphrontRedirectResponse())->setURI('/bulk/edit/');

// after: carry a saved query key from the search that produced the set
$uri = '/bulk/edit/?queryKey='.$saved_query->getQueryKey();
return id(new AphrontRedirectResponse())->setURI($uri);
Defensive patterns

Strategy: validation

Validate before calling

// Dispatch to the bulk flow only when a query is actually specified.
$query_key = $request->getStr('queryKey');
$request_data = $request->getPassthroughRequestData();
if (!strlen($query_key) && !$request_data) {
  // redirect the user to the search UI to pick a query first
}

Prevention

When it happens

Trigger: A bare GET to the bulk edit endpoint with no query key in the URI and no POSTed search parameters; custom controllers linking into the bulk flow without forwarding either.

Common situations: Bookmarked or hand-built bulk-edit URLs missing the query parameter; integrations that open the bulk editor without the user running a search first.

Related errors


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