Merge request list API returns an empty list for reviewer_username=None and reviewer_username=Any

Summary

GET /merge_requests, GET /projects/:id/merge_requests and GET /groups/:id/merge_requests document reviewer_username like this: "None returns merge requests with no reviewers. Any returns merge requests with any reviewer." Both values return an empty list. The same values work in reviewer_id.

I found this while checking the merge request filters of gitlab-mcp-server against this API.

Steps to reproduce

Compare the same wildcards in reviewer_id and reviewer_username:

for q in reviewer_id=None reviewer_username=None reviewer_id=Any reviewer_username=Any; do
  echo "$q: $(curl --silent --header "PRIVATE-TOKEN: <your_access_token>" \
    "https://gitlab.com/api/v4/projects/278964/merge_requests?state=opened&per_page=5&$q" \
    | jq -c '[length, [.[].iid], [.[].reviewers | length]]')"
done

Example Project

Any project; the output below is from gitlab-org/gitlab on GitLab.com.

What is the current bug behavior?

reviewer_username=None and reviewer_username=Any return []. Lowercase none does the same.

What is the expected correct behavior?

What the description says and reviewer_id already does: None returns merge requests with no reviewers, Any those with at least one.

Relevant logs and/or screenshots

GitLab.com, 27 October 2026 (count, merge request IIDs, reviewers of each):

reviewer_id=None: [5,[265364,265363,265361,265358,265357],[0,0,0,0,0]]
reviewer_username=None: [0,[],[]]
reviewer_id=Any: [5,[265362,265360,265359,265354,265353],[2,1,1,2,1]]
reviewer_username=Any: [0,[],[]]

Output of checks

This bug happens on GitLab.com.

Possible fixes

MergeRequestsFinder::Params#filter_by_no_reviewer? and #filter_by_any_reviewer? read only params[:reviewer_id] (params.rb lines 7-13), so MergeRequestsFinder#by_reviewer (lines 260-272) looks up a user named None and returns items.none.

The finder could read the wildcard from reviewer_username when reviewer_id is not given, the precedence Params#reviewer already uses. IssuableFinder#specific_user_filter? (lines 480-486) already counts these values as wildcards, and approved_by_usernames accepts them (by_approvals_finder.rb lines 59-60). A user named none or any could then be filtered as a reviewer only through reviewer_id, the trade-off approved_by_usernames already makes. The docs have promised the wildcards since 13.8, so I'd rather make them work than drop the two sentences; I have a merge request ready.

Related, not part of this issue: the negated reviewer filters

not[reviewer_id] is declared Integer (line 108), so not[reviewer_id]=None is refused with 400, and not[reviewer_username]=None returns [], yet both descriptions carry the same None and Any sentences. What the wildcards should mean under not is a separate question; I can open an issue for it.

Edited by 🤖 GitLab Bot 🤖