quarkusio/quarkus · error · IllegalArgumentException

Unsupported Map type '{type.name()}'. Offending method is: {

Error message

Unsupported Map type '{type.name()}'. Offending method is: {jandexMethod}

What it means

The client processor only supports `Map` and `MultivaluedMap` as the map-like parameter type for header/form handling. Any other Map subtype (e.g. `HashMap`, `SortedMap`, or a custom Map implementation) is unsupported because the processor cannot reliably resolve its key/value parameters. Deployment fails with this IllegalArgumentException.

Source

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

            if (type.kind() != PARAMETERIZED_TYPE) {
                throw new IllegalArgumentException(
                        "Raw Map parameter types are not supported. Offending method is: " + jandexMethod);
            }
            var parameterizedType = type.asParameterizedType();
            var arguments = parameterizedType.arguments();
            return new AbstractMap.SimpleEntry<>(arguments.get(0), arguments.get(1));
        } else if (type.name().equals(ResteasyReactiveDotNames.MULTI_VALUED_MAP)) {
            if (type.kind() != PARAMETERIZED_TYPE) {
                throw new IllegalArgumentException(
                        "Raw MultivaluedMap parameter types are not supported. Offending method is: " + jandexMethod);
            }
            var parameterizedType = type.asParameterizedType();
            var arguments = parameterizedType.arguments();
            return new AbstractMap.SimpleEntry<>(arguments.get(0), ParameterizedType.create(ResteasyReactiveDotNames.LIST,
                    new Type[] { arguments.get(1) }, null));
        }
        // TODO: we could support this if necessary by looking up the resolved types via JandexUtil.resolveTypeParameters
        throw new IllegalArgumentException("Unsupported Map type '" + type.name() + "'. Offending method is: " + jandexMethod);
    }

    private BranchResult iteratorHasNext(BytecodeCreator creator, ResultHandle iterator) {
        return creator.ifTrue(
                creator.invokeInterfaceMethod(ofMethod(Iterator.class, "hasNext", boolean.class), iterator));
    }

    private void addWebTargetParamToWebTarget(BytecodeCreator creator, ResultHandle paramName,
            ResultHandle webTarget,
            ResultHandle client, ResultHandle genericType,
            ResultHandle paramAnnotations, ResultHandle paramArray,
            String componentType,
            AssignableResultHandle resultVariable,
            String webTargetParamMethod,
            String separator) {
        ResultHandle convertedParamArray = creator.invokeVirtualMethod(
                MethodDescriptor.ofMethod(RestClientBase.class, "convertParamArray", Object[].class, Object[].class,
                        Class.class, java.lang.reflect.Type.class, Annotation[].class, String.class),

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the parameter type to the exact interface `Map<String, String>` (or `MultivaluedMap<String, String>`), keeping subtype instantiation only at the call site
  2. Pass the data as a dedicated POJO/DTO instead of a Map subtype
  3. If truly needed upstream support, this would require Jandex type resolution — currently not implemented (see TODO in processor)

Example fix

// before
@POST void send(@HeaderParam("h") HashMap<String, String> headers);
// after
@POST void send(@HeaderParam("h") Map<String, String> headers);
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = param.getClass(); if (!c.equals(Map.class) && !c.equals(MultivaluedMap.class) && Map.class.isAssignableFrom(c)) throw new IllegalArgumentException("Use exact Map or MultivaluedMap interface in REST client signatures");

Type guard

static boolean isSupportedMapType(java.lang.reflect.Type t) { return t.equals(Map.class) || (t instanceof ParameterizedType pt && (pt.getRawType().equals(Map.class) || pt.getRawType().equals(MultivaluedMap.class))); }

Prevention

When it happens

Trigger: Using a Map subtype such as `HashMap<String, String>` or `TreeMap<String, String>` as a REST client method parameter for headers/form params instead of the exact `Map` or `MultivaluedMap` interface.

Common situations: Using a concrete implementation type for convenience; custom Map wrappers to add helper methods; signatures copied from other frameworks that accept subtypes.

Related errors


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