quarkusio/quarkus · error · RuntimeException

Cannot handle wildcard type

Error message

Cannot handle wildcard type 

What it means

When converting indexed types to class names, EndpointIndexer.toClassName cannot represent a wildcard type with an unbounded/Object bound (e.g. ? or List<?>). Only wildcards with a meaningful extends bound are supported (the bound is used instead). It throws a RuntimeException, typically surfaced wrapped by error 3383.

Source

Thrown at independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java:1149

    protected static String toClassName(Type indexType, ClassInfo currentClass, ClassInfo actualEndpointClass,
            IndexView indexView) {
        switch (indexType.kind()) {
            case VOID:
                return "void";
            case CLASS:
                return indexType.asClassType().name().toString();
            case PRIMITIVE:
                return indexType.asPrimitiveType().primitive().name().toLowerCase(Locale.ENGLISH);
            case PARAMETERIZED_TYPE:
                return indexType.asParameterizedType().name().toString();
            case ARRAY:
                return indexType.asArrayType().name().toString();
            case WILDCARD_TYPE:
                WildcardType wildcardType = indexType.asWildcardType();
                Type extendsBound = wildcardType.extendsBound();
                if (extendsBound.name().equals(OBJECT)) {
                    // this is a super bound type that we don't support
                    throw new RuntimeException("Cannot handle wildcard type " + indexType);
                }
                // this is an extend bound type, so we just user the bound
                return wildcardType.name().toString();
            case TYPE_VARIABLE:
                TypeVariable typeVariable = indexType.asTypeVariable();
                if (typeVariable.bounds().isEmpty()) {
                    return Object.class.getName();
                }

                return toClassName(resolveTypeVariable(typeVariable, currentClass, actualEndpointClass, indexView),
                        currentClass, actualEndpointClass, indexView);
            default:
                throw new RuntimeException("Unknown parameter type " + indexType);
        }
    }

    private static Type resolveTypeVariable(TypeVariable typeVariable, ClassInfo currentClass, ClassInfo actualEndpointClass,
            IndexView indexView) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Replace the unbounded wildcard with a concrete type (e.g. List<String> instead of List<?>)
  2. Use an explicit extends bound (e.g. List<? extends Number>) if subtype flexibility is needed
  3. Move the wildcard-typed logic out of the endpoint signature into internal code with concrete types

Example fix

// before
@GET
public List<?> list() { ... }
// after
@GET
public List<String> list() { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

static <T> Class<T> requireConcrete(java.lang.reflect.Type t) {
    if (t instanceof ParameterizedType pt) {
        for (java.lang.reflect.Type arg : pt.getActualTypeArguments()) {
            if (arg instanceof WildcardType wt
                && (wt.getUpperBounds().length == 0 || wt.getUpperBounds()[0] == Object.class)
                && wt.getLowerBounds().length == 0)
                throw new IllegalArgumentException("Unbounded wildcard not allowed: " + t);
            requireConcrete(arg);
        }
    }
    return null;
}

Type guard

static boolean isSupportedEndpointType(java.lang.reflect.Type t) {
    if (t instanceof WildcardType wt) {
        return wt.getUpperBounds().length > 0 && wt.getUpperBounds()[0] != Object.class;
    }
    if (t instanceof ParameterizedType pt) {
        return java.util.Arrays.stream(pt.getActualTypeArguments())
            .allMatch(MyChecks::isSupportedEndpointType);
    }
    return !(t instanceof WildcardType);
}

Prevention

When it happens

Trigger: A resource method signature uses an unbounded wildcard generic such as List<?>, Map<String,?>, or a parameter/return type of ? with no extends bound, and Quarkus indexes the endpoint.

Common situations: Generic helper signatures reused in resource methods; returning ResponseEntity<List<?>> style types; copy-pasting repository/DAO generic types into endpoints.

Related errors


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