quarkusio/quarkus · error · IllegalArgumentException

Unsupported type: " + type

Error message

Unsupported type: " + type

What it means

The Redis cache deployment processor's typeToString converts Jandex Types into type strings for value-type configuration. Parameterized types with an owner type (e.g. Outer.Inner<...> where Inner is a nested class of Outer) are not supported by this converter, so it throws IllegalArgumentException.

Source

Thrown at extensions/redis-cache/deployment/src/main/java/io/quarkus/cache/redis/deployment/RedisCacheProcessor.java:219

        return result;
    }

    private static String typeToString(Type type) {
        StringBuilder result = new StringBuilder();
        typeToString(type, result);
        return result.toString();
    }

    private static void typeToString(Type type, StringBuilder result) {
        switch (type.kind()) {
            case VOID, PRIMITIVE, CLASS -> result.append(type.name().toString());
            case ARRAY -> {
                typeToString(type.asArrayType().elementType(), result);
                result.append("[]".repeat(type.asArrayType().deepDimensions()));
            }
            case PARAMETERIZED_TYPE -> {
                if (type.asParameterizedType().owner() != null) {
                    throw new IllegalArgumentException("Unsupported type: " + type);
                }

                result.append(type.name().toString());
                result.append('<');
                boolean first = true;
                for (Type typeArgument : type.asParameterizedType().arguments()) {
                    if (!first) {
                        result.append(", ");
                    }
                    typeToString(typeArgument, result);
                    first = false;
                }
                result.append('>');
            }
            case WILDCARD_TYPE -> {
                result.append('?');
                if (type.asWildcardType().superBound() != null) {
                    result.append(" super ");

View on GitHub (pinned to e1c734241f)

Solutions

  1. Refactor the cached type to a top-level class instead of a nested/inner parameterized class
  2. Cache a simpler type (e.g. a record or wrapper at top level) and map to the nested type outside the cache
  3. File/upgrade: check the Quarkus version for fixes to redis-cache type handling and upgrade
  4. Configure value-type with the raw class form if generics are not essential for marshalling

Example fix

// before
class Container {
  static class Payload<T> { T data; }
}
@CacheResult(cacheName="c") Container.Payload<Item> load();
// after
class Payload<T> { T data; }  // top-level class
@CacheResult(cacheName="c") Payload<Item> load();
Defensive patterns

Strategy: validation

Validate before calling

if (valueClass.isMemberClass() || valueClass.getEnclosingClass() != null) {
    throw new IllegalArgumentException("Move " + valueClass + " to a top-level class for Redis caching");
}

Type guard

static boolean isTopLevel(Class<?> c) { return c.getEnclosingClass() == null; }

Prevention

When it happens

Trigger: A cached method (or configured value-type) whose type is a member/nested parameterized class with a non-null owner, e.g. java.util.Map.Entry-style nested generic classes, reaches typeToString during deployment.

Common situations: Caching methods that return nested generic inner classes like Container.Payload<Thing>; using such a type as a type argument in List<Outer.Inner<X>>; newer Quarkus versions that started applying type conversion to previously ignored types.

Related errors


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