quarkusio/quarkus · error · IllegalStateException

Invalid type:

Error message

Invalid type: 

What it means

The @CachedResults annotation target resolved to a Jandex Type whose kind is not CLASS (e.g. parameterized type, array, primitive, type variable). The generated cache-result producer needs a concrete class/interface name to index, so non-class types are rejected at build time.

Source

Thrown at extensions/cache/deployment/src/main/java/io/quarkus/cache/deployment/CachedResultsProcessor.java:348

        AnnotationValue keyGeneratorValue = annotation.value("keyGenerator");
        if (keyGeneratorValue != null)
            keyGenerator = keyGeneratorValue.asClass().name();

        AnnotationValue excludeValue = annotation.value("exclude");
        if (excludeValue != null)
            exclude = excludeValue.asString();

        if (annotation.target().kind() == Kind.FIELD) {
            type = annotation.target().asField().type();
        } else if (annotation.target().kind() == Kind.METHOD_PARAMETER) {
            type = annotation.target().asMethodParameter().type();
        } else {
            throw new IllegalStateException("Unsupported target:" + annotation.target());
        }

        if (type.kind() != Type.Kind.CLASS) {
            throw new IllegalStateException("Invalid type: " + type);
        }
        ClassInfo injectedClazz = index.getClassByName(type.name());
        if (injectedClazz == null) {
            throw new IllegalStateException("Injected class not found in index: " + type.name());
        }
        if (!injectedClazz.isInterface()
                && !injectedClazz.hasNoArgsConstructor()) {
            throw new IllegalStateException(
                    "@CachedResults class must be an interface or declare a no-args constructor: " + injectedClazz);
        }
        return new CachedResultsInjectConfig(cacheName, lockTimeout, keyGenerator, injectedClazz,
                // consider all but @CachedResults and @Inject
                annotation.target().declaredAnnotations().stream().filter(
                        a -> !a.name().equals(CACHED_RESULTS)
                                && !a.name().equals(INJECT))
                        .toList(),
                exclude);
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Declare the injected field/parameter with a raw class or interface type (no generics, no arrays).
  2. If you need a parameterized type, introduce a dedicated non-generic interface/class and inject that.
  3. Check for compiler/Lombok/annotation-processor artifacts altering the declared type signature.

Example fix

// before
@Inject @CachedResults
List<CachedResult> results;

// after
@Inject @CachedResults
CachedResultList results; // plain interface/class type
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the annotated injection point declares a raw class/interface type
Field f = MyClass.class.getDeclaredField("result");
if (f.getGenericType() instanceof ParameterizedType || f.getType().isArray()) {
    throw new IllegalStateException("@CachedResults target must be a plain class/interface type");
}

Type guard

static boolean isPlainClassType(java.lang.reflect.Field f) {
    return !f.getGenericType().toString().contains("<") && !f.getType().isArray();
}

Prevention

When it happens

Trigger: Annotating an injection point whose declared type is generic (e.g. `List<String>`), an array, a primitive wrapper resolved oddly, or a type variable rather than a plain class/interface type.

Common situations: Injecting `@CachedResults SomeGeneric<T>`, injecting an array type, or Kotlin/other-language generated signatures producing PARAMETERIZED_TYPE instead of CLASS.

Related errors


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