quarkusio/quarkus · error · IllegalStateException

A resource method cannot be simultaneously annotated with '@

Error message

A resource method cannot be simultaneously annotated with '@Cache' and '@NoCache'. Offending method is '${methodInfo.name()}' of class '${methodInfo.declaringClass().name()}'

What it means

@Cache and @NoCache both control Cache-Control headers on resource methods and are mutually exclusive. CacheControlScanner.doScan detects both on the same method during endpoint scanning and throws IllegalStateException at build time, since emitting both directives would be contradictory.

Source

Thrown at independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/CacheControlScanner.java:62

            // first check bean implementation
            List<HandlerChainCustomizer> customizers = doScan(actualMethod, actualEndpointClass, methodContext);
            if (customizers.isEmpty()) {
                // if no annotations where found on implementation, check the interface
                customizers = doScan(method, currentClassInfo, methodContext);
            }
            return customizers;
        } else {
            return doScan(method, actualEndpointClass, methodContext);
        }
    }

    private List<HandlerChainCustomizer> doScan(MethodInfo methodInfo, ClassInfo classInfo,
            Map<String, Object> methodContext) {
        AnnotationStore annotationStore = (AnnotationStore) methodContext.get(EndpointIndexer.METHOD_CONTEXT_ANNOTATION_STORE);
        ExtendedCacheControl cacheControl = noCacheToCacheControl(annotationStore.getAnnotation(methodInfo, NO_CACHE));
        if (cacheControl != null) {
            if (methodInfo.annotation(CACHE) != null) {
                throw new IllegalStateException(
                        "A resource method cannot be simultaneously annotated with '@Cache' and '@NoCache'. Offending method is '"
                                + methodInfo.name() + "' of class '" + methodInfo.declaringClass().name() + "'");
            }
            return cacheControlToCustomizerList(cacheControl);
        } else {
            cacheControl = noCacheToCacheControl(annotationStore.getAnnotation(classInfo, NO_CACHE));
            if (cacheControl != null) {
                if (classInfo.declaredAnnotation(CACHE) != null) {
                    throw new IllegalStateException(
                            "A resource class cannot be simultaneously annotated with '@Cache' and '@NoCache'. Offending class is '"
                                    + classInfo.name() + "'");
                }
                return cacheControlToCustomizerList(cacheControl);
            }
        }

        cacheControl = cacheToCacheControl(methodInfo.annotation(CACHE));
        if (cacheControl != null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove @NoCache from the method if it should be cached.
  2. Remove the class-level or method-level @Cache for methods that must not be cached, keeping only @NoCache.
  3. Split caching policies across separate resource classes/methods so each carries exactly one of the two annotations.

Example fix

// before
@Cache(maxAge = 3600)
@NoCache
@GET
public String get() { ... }
// after
@NoCache
@GET
public String get() { ... }
Defensive patterns

Strategy: validation

Validate before calling

import jakarta.ws.rs.GET;
// class-level check before build:
Cache cache = resourceClass.getAnnotation(Cache.class);
for (Method m : resourceClass.getDeclaredMethods()) {
    boolean methodNoCache = m.isAnnotationPresent(NoCache.class);
    if (cache != null && methodNoCache && java.util.Arrays.stream(m.getAnnotations())
            .anyMatch(a -> a.annotationType().getName().equals("io.quarkus.cache.Cache"))) {
        throw new IllegalStateException("@Cache + @NoCache on " + m);
    }
}

Prevention

When it happens

Trigger: Annotating a JAX-RS resource method with both `@Cache` (method- or class-level) and `@NoCache` and building the application.

Common situations: Adding @NoCache to a single method to override a class-level @Cache — not allowed; merging resource classes with different caching strategies; copy-pasting annotations.

Related errors


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