{"record":{"id":"ecc7e80fd0e797e0","repo":"quarkusio/quarkus","slug":"a-resource-method-cannot-be-simultaneously-annotat","errorCode":null,"errorMessage":"A resource method cannot be simultaneously annotated with '@Cache' and '@NoCache'. Offending method is '${methodInfo.name()}' of class '${methodInfo.declaringClass().name()}'","messagePattern":"A resource method cannot be simultaneously annotated with '@Cache' and '@NoCache'\\. Offending method is '(.+?)' of class '(.+?)'","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/CacheControlScanner.java","lineNumber":62,"sourceCode":"            // first check bean implementation\n            List<HandlerChainCustomizer> customizers = doScan(actualMethod, actualEndpointClass, methodContext);\n            if (customizers.isEmpty()) {\n                // if no annotations where found on implementation, check the interface\n                customizers = doScan(method, currentClassInfo, methodContext);\n            }\n            return customizers;\n        } else {\n            return doScan(method, actualEndpointClass, methodContext);\n        }\n    }\n\n    private List<HandlerChainCustomizer> doScan(MethodInfo methodInfo, ClassInfo classInfo,\n            Map<String, Object> methodContext) {\n        AnnotationStore annotationStore = (AnnotationStore) methodContext.get(EndpointIndexer.METHOD_CONTEXT_ANNOTATION_STORE);\n        ExtendedCacheControl cacheControl = noCacheToCacheControl(annotationStore.getAnnotation(methodInfo, NO_CACHE));\n        if (cacheControl != null) {\n            if (methodInfo.annotation(CACHE) != null) {\n                throw new IllegalStateException(\n                        \"A resource method cannot be simultaneously annotated with '@Cache' and '@NoCache'. Offending method is '\"\n                                + methodInfo.name() + \"' of class '\" + methodInfo.declaringClass().name() + \"'\");\n            }\n            return cacheControlToCustomizerList(cacheControl);\n        } else {\n            cacheControl = noCacheToCacheControl(annotationStore.getAnnotation(classInfo, NO_CACHE));\n            if (cacheControl != null) {\n                if (classInfo.declaredAnnotation(CACHE) != null) {\n                    throw new IllegalStateException(\n                            \"A resource class cannot be simultaneously annotated with '@Cache' and '@NoCache'. Offending class is '\"\n                                    + classInfo.name() + \"'\");\n                }\n                return cacheControlToCustomizerList(cacheControl);\n            }\n        }\n\n        cacheControl = cacheToCacheControl(methodInfo.annotation(CACHE));\n        if (cacheControl != null) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/CacheControlScanner.java#L44-L80","documentation":"@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.","triggerScenarios":"Annotating a JAX-RS resource method with both `@Cache` (method- or class-level) and `@NoCache` and building the application.","commonSituations":"Adding @NoCache to a single method to override a class-level @Cache — not allowed; merging resource classes with different caching strategies; copy-pasting annotations.","solutions":["Remove @NoCache from the method if it should be cached.","Remove the class-level or method-level @Cache for methods that must not be cached, keeping only @NoCache.","Split caching policies across separate resource classes/methods so each carries exactly one of the two annotations."],"exampleFix":"// before\n@Cache(maxAge = 3600)\n@NoCache\n@GET\npublic String get() { ... }\n// after\n@NoCache\n@GET\npublic String get() { ... }","handlingStrategy":"validation","validationCode":"import jakarta.ws.rs.GET;\n// class-level check before build:\nCache cache = resourceClass.getAnnotation(Cache.class);\nfor (Method m : resourceClass.getDeclaredMethods()) {\n    boolean methodNoCache = m.isAnnotationPresent(NoCache.class);\n    if (cache != null && methodNoCache && java.util.Arrays.stream(m.getAnnotations())\n            .anyMatch(a -> a.annotationType().getName().equals(\"io.quarkus.cache.Cache\"))) {\n        throw new IllegalStateException(\"@Cache + @NoCache on \" + m);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never combine @Cache and @NoCache on the same resource method.","Remember @NoCache cannot override a class-level @Cache — remove one of them.","Keep a single caching policy per resource class.","Search the codebase for both annotations during code review of caching changes."],"tags":["quarkus","resteasy-reactive","build-time","cache-control","annotations"],"backgroundTag":"conflicting-cache-annotations","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}