quarkusio/quarkus · error · IllegalArgumentException
Variant list must not be empty
Error message
Variant list must not be empty
What it means
RequestImpl.selectVariant() throws IllegalArgumentException because the JAX-RS contract requires a non-null, non-empty variant list when performing server-driven content negotiation. The library cannot negotiate against zero candidates.
Source
Thrown at independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/jaxrs/RequestImpl.java:42
public RequestImpl(ResteasyReactiveRequestContext requestContext) {
this.requestContext = requestContext;
this.httpMethod = requestContext.serverRequest().getRequestMethod();
}
@Override
public String getMethod() {
return requestContext.serverRequest().getRequestMethod();
}
private boolean isRfc7232preconditions() {
return true;//todo: do we need config for this?
}
@Override
public Variant selectVariant(List<Variant> variants) throws IllegalArgumentException {
if (variants == null || variants.size() == 0)
throw new IllegalArgumentException("Variant list must not be empty");
ServerDrivenNegotiation negotiation = new ServerDrivenNegotiation();
MultivaluedMap<String, String> requestHeaders = requestContext.getHttpHeaders().getRequestHeaders();
negotiation.setAcceptHeaders(requestHeaders.get(HttpHeaders.ACCEPT));
negotiation.setAcceptCharsetHeaders(requestHeaders.get(HttpHeaders.ACCEPT_CHARSET));
negotiation.setAcceptEncodingHeaders(requestHeaders.get(HttpHeaders.ACCEPT_ENCODING));
negotiation.setAcceptLanguageHeaders(requestHeaders.get(HttpHeaders.ACCEPT_LANGUAGE));
varyHeader = AbstractResponseBuilder.createVaryHeader(variants);
requestContext.serverResponse().setResponseHeader(HttpHeaders.VARY, varyHeader);
//response.getOutputHeaders().add(VARY, varyHeader);
return negotiation.getBestMatch(variants);
}
private List<EntityTag> convertEtag(List<String> tags) {
ArrayList<EntityTag> result = new ArrayList<EntityTag>();
for (String tag : tags) {
String[] split = tag.split(",");View on GitHub (pinned to e1c734241f)
Solutions
- Populate the Variant list with at least one Variant before calling selectVariant().
- Guard the call: only invoke selectVariant when the list is non-empty, otherwise return a default representation or 406.
- Verify VariantListBuilder usage: addXXX(...) followed by add() actually appended the variants.
Example fix
// before
Variant v = request.selectVariant(variants);
// after
if (variants == null || variants.isEmpty()) {
throw new NotAcceptableException();
}
Variant v = request.selectVariant(variants); Defensive patterns
Strategy: validation
Validate before calling
if (variants == null || variants.isEmpty()) {
throw new NotAcceptableException("No producible variants");
} Type guard
boolean negotiable(List<Variant> v) {
return v != null && !v.isEmpty();
} Try / catch
try {
return request.selectVariant(variants);
} catch (IllegalArgumentException e) {
throw new NotAcceptableException(e.getMessage());
} Prevention
- Never call selectVariant with an empty list
- Build variants with VariantListBuilder and call add() per variant
- Default to a fallback representation when variants are absent
When it happens
Trigger: Calling request.selectVariant(List<Variant>) with null or an empty list (e.g. Variant.encodings(...).build() produced no variants or a filter removed them all).
Common situations: Building variants from configuration or a database that returned no rows; passing a list built conditionally where every branch was skipped; API misuse where variants were intended to be added after the call.
Related errors
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4e206e7d65f023ba.
Report an issue: GitHub.