quarkusio/quarkus · error · IllegalStateException
A resource class cannot be simultaneously annotated with '@C
Error message
A resource class cannot be simultaneously annotated with '@Cache' and '@NoCache'. Offending class is '${classInfo.name()}' What it means
RESTEasy Reactive lets you declare cache-control behavior on resource classes via @Cache and @NoCache annotations. These are mutually exclusive, so during the build-time scan (CacheControlScanner.doScan) a class declaring both is rejected with this IllegalStateException to fail the deployment fast rather than produce ambiguous caching behavior.
Source
Thrown at independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/CacheControlScanner.java:71
}
}
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) {
return cacheControlToCustomizerList(cacheControl);
} else {
cacheControl = cacheToCacheControl(classInfo.declaredAnnotation(CACHE));
if (cacheControl != null) {
return cacheControlToCustomizerList(cacheControl);
}
}
return Collections.emptyList();View on GitHub (pinned to e1c734241f)
Solutions
- Remove either @Cache or @NoCache from the offending class (the class name is given in the message).
- If inheritance is involved, keep the cache-control annotation on exactly one level of the class hierarchy.
- Decide the intended caching semantics: @Cache for cacheable responses, @NoCache to force revalidation, and annotate only with that one.
Example fix
// before
@Cache(maxAge = 3600)
@NoCache
public class MyResource { ... }
// after
@Cache(maxAge = 3600)
public class MyResource { ... } Defensive patterns
Strategy: validation
Validate before calling
if (resourceClass.isAnnotationPresent(Cache.class) && resourceClass.isAnnotationPresent(NoCache.class)) {
throw new IllegalStateException(resourceClass + " has both @Cache and @NoCache");
} Type guard
boolean hasConflictingCacheAnnotations(ClassInfo classInfo) {
return classInfo.declaredAnnotation("jakarta.ws.rs.Cache") != null
&& classInfo.declaredAnnotation("jakarta.ws.rs.NoCache") != null;
} Try / catch
try {
scanner.doScan(...);
} catch (IllegalStateException e) {
if (e.getMessage().contains("'@Cache' and '@NoCache'")) {
log.error("Remove one of the conflicting annotations: " + e.getMessage());
}
throw e;
} Prevention
- Annotate cache-control at exactly one hierarchy level per resource class.
- Review imports after copy-pasting annotation blocks.
- Add an ArchUnit or build-time check asserting no class declares both annotations.
- Search the codebase for classes annotated with @NoCache before adding @Cache anywhere in the hierarchy.
When it happens
Trigger: Annotating the same JAX-RS resource class with both @Cache (or @Cache with variants) and @NoCache, typically by accident when annotations accumulate on a class over time or are added at both class and subclass levels that get merged.
Common situations: Copy-pasting annotation blocks from another resource; a base class annotated @NoCache while a subclass adds @Cache; IDE auto-imports adding the wrong annotation alongside the intended one.
Related errors
- Parameter: ${i} of the constructor of class '${resourceDotNa
- Parameter: ${i} of the constructor of class '${resourceDotNa
- Unsupported type '${jaxRSAnnotationOfParam.name()}' used as
- The combination of '@${annotationName}' and '@ServerRequestF
- The combination of '@${annotationName}' and '@ServerExceptio
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/59be2aa8aeed743b.
Report an issue: GitHub.