Elasticsearch BadRequest error when paginating merge request search results beyond page 100
Summary
Users searching for merge requests via Elasticsearch encounter a 400 Bad Request error when navigating to search result pages beyond page 100 (i.e., when the from offset exceeds 10,000).
Error
Elasticsearch::Transport::Transport::Errors::BadRequest
[400] {"error":{"root_cause":[{"type":"illegal_argument_exception",
"reason":"Result window is too large, from + size must be less than or equal to: [10000] but was [10100].
See the scroll api for a more efficient way to request large data sets.
This limit can be set by changing the [index.max_result_window] index level setting."}]}}Sentry: https://new-sentry.gitlab.net/organizations/gitlab/issues/3545713/
Root Cause
Search::Elastic::MergeRequestQueryBuilder#build calls Formats.size to set the result size, but does not call Formats.page to set the from offset. This means the from field is never included in the Elasticsearch query for merge request searches.
When a user navigates to page 101 (with 100 results per page), the effective from value would be 100 * 100 = 10,000, which hits Elasticsearch's default index.max_result_window limit of 10,000. At page 102 (from = 10,100), the request fails with a BadRequest.
Compare with ProjectQueryBuilder#build and WorkItemQueryBuilder#build, which both correctly call Formats.page:
# ee/lib/search/elastic/project_query_builder.rb
query_hash = ::Search::Elastic::Formats.page(query_hash: query_hash, options: options)
query_hash = ::Search::Elastic::Formats.size(query_hash: query_hash, options: options)But MergeRequestQueryBuilder only calls:
# ee/lib/search/elastic/merge_request_query_builder.rb
query_hash = ::Search::Elastic::Formats.size(query_hash: query_hash, options: options)
# Formats.page is missing!Additionally, there is no guard to cap the from + size value at ELASTIC_COUNT_LIMIT (10,000), which is already defined in Gitlab::Elastic::SearchResults.
Impact
- Any user performing a merge request search with enough results to paginate past page 100 will receive a 500 error.
- Affects GitLab.com production (
gprdenvironment).
Proposed Fix
- Add
Formats.pagecall toMergeRequestQueryBuilder#build(similar toProjectQueryBuilder). - Consider adding a guard in
Formats.pageor the search controller to capfrom + sizeatELASTIC_COUNT_LIMIT(10,000) to prevent this class of error across all search types.
Steps to Reproduce
- Enable Elasticsearch/Advanced Search on a GitLab instance with many merge requests.
- Search for a common term that returns more than 10,000 merge request results.
- Navigate to page 101 or beyond.