{"record":{"id":"f331b5a4fdedf388","repo":"quarkusio/quarkus","slug":"map-parameter-types-must-have-string-keys-offendi","errorCode":null,"errorMessage":"Map parameter types must have String keys. Offending method is: {jandexMethod}","messagePattern":"Map parameter types must have String keys\\. Offending method is: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java","lineNumber":3256,"sourceCode":"            String paramName,\n            ResultHandle paramHandle,\n            Type type,\n            IndexView index,\n            // this client or containing client if we're in a subresource\n            ResultHandle client,\n            ResultHandle genericType,\n            ResultHandle paramAnnotations,\n            String webTargetParamMethod,\n            String separator) {\n\n        AssignableResultHandle result = methodCreator.createVariable(WebTarget.class);\n        BranchResult isParamNull = methodCreator.ifNull(paramHandle);\n        BytecodeCreator notNullParam = isParamNull.falseBranch();\n        if (isMap(type, index)) {\n            var resolvesTypes = resolveMapTypes(type, jandexMethod);\n            var keyType = resolvesTypes.getKey();\n            if (!ResteasyReactiveDotNames.STRING.equals(keyType.name())) {\n                throw new IllegalArgumentException(\n                        \"Map parameter types must have String keys. Offending method is: \" + jandexMethod);\n            }\n            notNullParam.assign(result, webTarget);\n            // Loop through the keys\n            ResultHandle keySet = notNullParam.invokeInterfaceMethod(ofMethod(Map.class, \"keySet\", Set.class),\n                    paramHandle);\n            ResultHandle keysIterator = notNullParam.invokeInterfaceMethod(\n                    ofMethod(Set.class, \"iterator\", Iterator.class), keySet);\n            BytecodeCreator loopCreator = notNullParam.whileLoop(c -> iteratorHasNext(c, keysIterator)).block();\n            ResultHandle key = loopCreator.invokeInterfaceMethod(\n                    ofMethod(Iterator.class, \"next\", Object.class), keysIterator);\n            // get the value and convert\n            ResultHandle value = loopCreator.invokeInterfaceMethod(ofMethod(Map.class, \"get\", Object.class, Object.class),\n                    paramHandle, key);\n            var valueType = resolvesTypes.getValue();\n            String componentType = valueType.name().toString();\n            ResultHandle paramArray;\n            if (isCollection(valueType, index)) {","sourceCodeStart":3238,"sourceCodeEnd":3274,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java#L3238-L3274","documentation":"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.","triggerScenarios":"Declaring `void get(Map<Integer, String> params)` (or any non-String key) as a query-param style Map parameter on a @RegisterRestClient interface method.","commonSituations":"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.","solutions":["Change the Map key type parameter to String: Map<String, String>","Convert non-String keys to Strings before calling and pass Map<String, ...>","If keys are enum/objects, pre-map them to their String names"],"exampleFix":"// before\n@GET\n@Path(\"search\")\nList<Item> search(Map<Integer, String> filters);\n// after\n@GET\n@Path(\"search\")\nList<Item> search(Map<String, String> filters);","handlingStrategy":"type-guard","validationCode":"static void requireStringKeys(Map<?, ?> params, String where) {\n    for (Object k : params.keySet()) {\n        if (!(k instanceof String)) {\n            throw new IllegalArgumentException(\n                where + \": Map keys must be String, got \" + k.getClass().getName());\n        }\n    }\n}","typeGuard":"static boolean isStringKeyedMap(Object o) {\n    if (!(o instanceof Map<?, ?> m)) return false;\n    return m.keySet().stream().allMatch(k -> k instanceof String);\n}","tryCatchPattern":null,"preventionTips":["Always declare client Map params as Map<String, String> (or Map<String, List<String>>)","Convert enum/object keys to String at the call site","Add an interface-level unit test that calls each method with sample params"],"tags":["quarkus","rest-client","map-parameters","generics"],"backgroundTag":"invalid-parameter-type","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}