Web API /api/issues/search returns total=0 for valid multi-comma resolutions= filter (CE 26.4)
Must-share information
- Which versions are you using:
- SonarQube Server 26.4.0.121862 Community Build
- MQR (Multi-Quality Rule) mode enabled
- Deployment: official Docker image
sonarqube:community - Database: PostgreSQL 15
- What are you trying to achieve:
Query issues filtered by multiple resolution values via
/api/issues/search?resolutions=A,B,C(e.g. to count all issues that
were triaged as eitherFALSE-POSITIVE,ACCEPTED, orWONTFIXin
one round trip). - What have you tried so far:
- Confirmed via
curlthat single-valueresolutions=FALSE-POSITIVE
works as documented. - Confirmed that any multi-value
resolutions=A,B[,C…]form returns
total=0, regardless of value order or which value the issue’s
actualresolutionfield matches. - Other comma-separated list parameters on the same endpoint
(statuses=,types=,severities=,impactSeverities=) work as
expected on the same instance. - Reproducible 100% on a fresh project after a clean scan and a
singledo_transitioncall.
- Confirmed via
Bug summary
The Web API endpoint /api/issues/search documents resolutions as a
comma-separated list of resolution values. In SonarQube Community Build
26.4 (MQR mode), passing more than one value through this parameter
silently returns total=0 and issues=[], even when matching issues
clearly exist (verified by querying with the same single value, by
querying without the filter, and by reading the resolution field of
the issue object directly).
The single-value form works. The multi-value form does not. There is no
HTTP error, no warning in the response payload, and no entry in
sonar.log — the result is a silent zero-result, which makes this
particularly painful for automation and CI pipelines.
Steps to reproduce
Setup
TOKEN="squ_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
URL="https://your-sonarqube.example.com"
PROJECT="your-project-key"
Step 1 — find one open VULNERABILITY issue and mark it FALSE-POSITIVE
KEY=$(curl -sf -u "$TOKEN:" \
"$URL/api/issues/search?componentKeys=$PROJECT&types=VULNERABILITY&statuses=OPEN&ps=1" \
| python3 -c 'import sys,json;d=json.load(sys.stdin);print(d["issues"][0]["key"])')
curl -sf -u "$TOKEN:" -X POST \
"$URL/api/issues/do_transition" \
-d "issue=$KEY&transition=falsepositive"
Step 2 — single-resolution query (works
)
curl -sf -u "$TOKEN:" \
"$URL/api/issues/search?issues=$KEY&resolutions=FALSE-POSITIVE&ps=1" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["total"])'
- Expected:
1 - Actual:
1— works as documented.
Step 3 — multi-comma resolutions query (broken
)
curl -sf -u "$TOKEN:" \
"$URL/api/issues/search?issues=$KEY&resolutions=FALSE-POSITIVE,ACCEPTED,WONTFIX,FIXED&ps=1" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["total"])'
- Expected:
1(the issue’sresolution=FALSE-POSITIVEmatches the
first value of the requested list). - Actual:
0— the bug.
Step 4 — ordering and combinations don’t help
# Matching value first:
curl -sf -u "$TOKEN:" "$URL/api/issues/search?issues=$KEY&resolutions=FALSE-POSITIVE,ACCEPTED&ps=1" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["total"])'
# Matching value second:
curl -sf -u "$TOKEN:" "$URL/api/issues/search?issues=$KEY&resolutions=ACCEPTED,FALSE-POSITIVE&ps=1" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["total"])'
# Hyphen-free values only (ACCEPTED,WONTFIX) — no FALSE-POSITIVE in the list:
curl -sf -u "$TOKEN:" "$URL/api/issues/search?issues=$KEY&resolutions=ACCEPTED,WONTFIX&ps=1" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["total"])'
# resolved=true without resolutions= (sanity check):
curl -sf -u "$TOKEN:" "$URL/api/issues/search?issues=$KEY&resolved=true&ps=1" \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["total"])'
- Actual:
0— multi-comma broken regardless of order.0— multi-comma broken regardless of order.0— multi-comma broken even when no value contains a hyphen
(so this is not a hyphen-parsing issue aroundFALSE-POSITIVE).1—resolved=true(withoutresolutions=) works as expected.
Expected behaviour
resolutions=A,B,C should match the union of issues whose resolution
field equals any of A, B, or C. This matches the behaviour of all
other comma-separated list parameters on the same endpoint
(statuses=, types=, severities=, impactSeverities=) and the
documented contract in the Web API specification.
Actual behaviour
resolutions=A,B,C returns total=0 and issues=[]. No HTTP error,
no warning, no log entry. Single-value resolutions=A returns the
matching issue correctly.
Workarounds
Three patterns we use in our automation while waiting for a fix:
-
Iterate per resolution and sum client-side:
total=0 for r in WONTFIX ACCEPTED FALSE-POSITIVE; do n=$(curl -sf -u "$TOKEN:" \ "$URL/api/issues/search?componentKeys=$PROJECT&resolutions=$r&ps=1" \ | python3 -c 'import sys,json;print(json.load(sys.stdin)["total"])') total=$((total + n)) done echo "$total" -
Drop
resolutions=filter, useresolved=trueand filter
client-side from the issue object:curl -sf -u "$TOKEN:" \ "$URL/api/issues/search?componentKeys=$PROJECT&resolved=true&ps=200" \ | python3 -c ' import sys,json d=json.load(sys.stdin) wanted={"FALSE-POSITIVE","ACCEPTED","WONTFIX"} print(sum(1 for i in d.get("issues",[]) if i.get("resolution","") in wanted)) ' -
Look up a known issue by key and read the
resolutionfield
directly:curl -sf -u "$TOKEN:" "$URL/api/issues/search?issues=$KEY&ps=1" \ | python3 -c 'import sys,json;i=json.load(sys.stdin)["issues"];print(i[0].get("resolution","") if i else "")'
All three are noticeably more verbose than what the documented
multi-comma form should provide.
Severity / impact
Medium. No data corruption, no security impact, but:
- Silent failure: a script using
resolutions=A,B,Clooks like it ran
successfully, just with zero matches. There is no signal for callers
to detect the misbehaviour. - Affects any automation, CI pipeline, or dashboard that aggregates
triaged issues across multiple resolution states — a common pattern
for governance reporting. - The documented API contract is broken, which makes the Web API less
trustworthy for consumers writing new integrations.
Additional information
-
Reproducible: 100% on the affected version, immediately after a
fresh scan and onedo_transitioncall. -
Single-value form works — confirms the issue exists and is found
by the resolution filter individually. -
Other comma-list parameters on the same endpoint work —
statuses=OPEN,REOPENED,CONFIRMED,types=VULNERABILITY,BUG,
severities=BLOCKER,CRITICALall return the correct union, on the
same instance and the same project. -
Hyphen is not the cause — the bug also affects all-uppercase
hyphen-free combinations such asresolutions=ACCEPTED,WONTFIX. -
No
sonar.logoutput when issuing the broken query at INFO
level. Did not test at DEBUG/TRACE, happy to provide if useful. -
Server / Edition:
GET /api/server/version → 26.4.0.121862 GET /api/system/info → Edition: "Community"
Happy to provide a HAR capture, raw response payloads, or a minimal
reproduction project if that would help triage. Thanks!