quarkusio/quarkus · error · IllegalArgumentException

Map parameter types must have String keys. Offending method

Error message

Map parameter types must have String keys. Offending method is: {jandexMethod}

What it means

A client method accepts a Map parameter (e.g. for query or matrix parameters). Quarkus must iterate its keys to build the URI, and it requires keys to be String so they can be encoded directly. A Map with non-String key types is rejected at build time.

Source

Thrown at extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java:3256

            String paramName,
            ResultHandle paramHandle,
            Type type,
            IndexView index,
            // this client or containing client if we're in a subresource
            ResultHandle client,
            ResultHandle genericType,
            ResultHandle paramAnnotations,
            String webTargetParamMethod,
            String separator) {

        AssignableResultHandle result = methodCreator.createVariable(WebTarget.class);
        BranchResult isParamNull = methodCreator.ifNull(paramHandle);
        BytecodeCreator notNullParam = isParamNull.falseBranch();
        if (isMap(type, index)) {
            var resolvesTypes = resolveMapTypes(type, jandexMethod);
            var keyType = resolvesTypes.getKey();
            if (!ResteasyReactiveDotNames.STRING.equals(keyType.name())) {
                throw new IllegalArgumentException(
                        "Map parameter types must have String keys. Offending method is: " + jandexMethod);
            }
            notNullParam.assign(result, webTarget);
            // Loop through the keys
            ResultHandle keySet = notNullParam.invokeInterfaceMethod(ofMethod(Map.class, "keySet", Set.class),
                    paramHandle);
            ResultHandle keysIterator = notNullParam.invokeInterfaceMethod(
                    ofMethod(Set.class, "iterator", Iterator.class), keySet);
            BytecodeCreator loopCreator = notNullParam.whileLoop(c -> iteratorHasNext(c, keysIterator)).block();
            ResultHandle key = loopCreator.invokeInterfaceMethod(
                    ofMethod(Iterator.class, "next", Object.class), keysIterator);
            // get the value and convert
            ResultHandle value = loopCreator.invokeInterfaceMethod(ofMethod(Map.class, "get", Object.class, Object.class),
                    paramHandle, key);
            var valueType = resolvesTypes.getValue();
            String componentType = valueType.name().toString();
            ResultHandle paramArray;
            if (isCollection(valueType, index)) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the Map key type parameter to String: Map<String, String>
  2. Convert non-String keys to Strings before calling and pass Map<String, ...>
  3. If keys are enum/objects, pre-map them to their String names

Example fix

// before
@GET
@Path("search")
List<Item> search(Map<Integer, String> filters);
// after
@GET
@Path("search")
List<Item> search(Map<String, String> filters);
Defensive patterns

Strategy: type-guard

Validate before calling

static void requireStringKeys(Map<?, ?> params, String where) {
    for (Object k : params.keySet()) {
        if (!(k instanceof String)) {
            throw new IllegalArgumentException(
                where + ": Map keys must be String, got " + k.getClass().getName());
        }
    }
}

Type guard

static boolean isStringKeyedMap(Object o) {
    if (!(o instanceof Map<?, ?> m)) return false;
    return m.keySet().stream().allMatch(k -> k instanceof String);
}

Prevention

When it happens

Trigger: Declaring `void get(Map<Integer, String> params)` (or any non-String key) as a query-param style Map parameter on a @RegisterRestClient interface method.

Common situations: Reusing an internal Map with Long/enum keys as a parameter bag; generic Map<K,V> where K resolves to a non-String type after type-variable resolution.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/f331b5a4fdedf388. Report an issue: GitHub.