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]]')"
doneExample 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.