{"record":{"id":"6abb825c3874f2de","repo":"quarkusio/quarkus","slug":"cachedresults-class-must-be-an-interface-or-decla","errorCode":null,"errorMessage":"@CachedResults class must be an interface or declare a no-args constructor: ","messagePattern":"@CachedResults class must be an interface or declare a no-args constructor: ","errorType":"error_code","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/cache/deployment/src/main/java/io/quarkus/cache/deployment/CachedResultsProcessor.java","lineNumber":356,"sourceCode":"\n        if (annotation.target().kind() == Kind.FIELD) {\n            type = annotation.target().asField().type();\n        } else if (annotation.target().kind() == Kind.METHOD_PARAMETER) {\n            type = annotation.target().asMethodParameter().type();\n        } else {\n            throw new IllegalStateException(\"Unsupported target:\" + annotation.target());\n        }\n\n        if (type.kind() != Type.Kind.CLASS) {\n            throw new IllegalStateException(\"Invalid type: \" + type);\n        }\n        ClassInfo injectedClazz = index.getClassByName(type.name());\n        if (injectedClazz == null) {\n            throw new IllegalStateException(\"Injected class not found in index: \" + type.name());\n        }\n        if (!injectedClazz.isInterface()\n                && !injectedClazz.hasNoArgsConstructor()) {\n            throw new IllegalStateException(\n                    \"@CachedResults class must be an interface or declare a no-args constructor: \" + injectedClazz);\n        }\n        return new CachedResultsInjectConfig(cacheName, lockTimeout, keyGenerator, injectedClazz,\n                // consider all but @CachedResults and @Inject\n                annotation.target().declaredAnnotations().stream().filter(\n                        a -> !a.name().equals(CACHED_RESULTS)\n                                && !a.name().equals(INJECT))\n                        .toList(),\n                exclude);\n    }\n\n    record CachedResultsInjectConfig(String cacheName, Long lockTimeout, DotName keyGenerator, ClassInfo injectedClazz,\n            Collection<AnnotationInstance> annotations, String exclude) {\n\n    }\n\n    record MethodKey(String name, List<TypeEquivalenceKey> params, TypeEquivalenceKey returnType) {\n","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/cache/deployment/src/main/java/io/quarkus/cache/deployment/CachedResultsProcessor.java#L338-L374","documentation":"The class injected with @CachedResults must either be an interface (so the extension can generate a synthetic caching implementation) or a concrete class with a public no-args constructor. Any other shape cannot be proxied/generated and the build fails.","triggerScenarios":"Annotating an injected concrete class that only has constructors taking arguments (no default constructor), or an abstract class without a no-arg constructor.","commonSituations":"Injecting a pre-existing service class with mandatory constructor dependencies and expecting @CachedResults to wrap it; migrating code from interface-based design to concrete classes.","solutions":["Make the injected type an interface and inject that.","Add a public no-arg constructor to the concrete class and supply dependencies another way (setters/field injection).","Move @CachedResults to a generated/accessor interface instead of caching the concrete class directly."],"exampleFix":"// before\n@ApplicationScoped\npublic class PriceService {\n    public PriceService(Config c) { ... }\n}\n\n// after\npublic interface PriceService { Price get(String id); }\n\n@Inject @CachedResults(cacheName = \"prices\")\nPriceService priceService; // interface target","handlingStrategy":"validation","validationCode":"Class<?> c = com.example.PriceService.class;\nif (!c.isInterface() && java.lang.reflect.Modifier.isAbstract(c.getModifiers())) {\n    throw new IllegalStateException(\"@CachedResults type must be an interface or concrete with no-arg ctor\");\n}\nif (!c.isInterface() && c.getDeclaredConstructors().length > 0\n        && java.util.Arrays.stream(c.getConstructors()).noneMatch(k -> k.getParameterCount() == 0)) {\n    throw new IllegalStateException(\"@CachedResults concrete class needs a public no-arg constructor\");\n}","typeGuard":"static boolean isValidCachedResultsType(Class<?> c) {\n    return c.isInterface() || java.util.Arrays.stream(c.getConstructors())\n            .anyMatch(k -> k.getParameterCount() == 0);\n}","tryCatchPattern":null,"preventionTips":["Design cached types as interfaces","If concrete, always provide a public no-arg constructor","Resolve dependencies via CDI injection fields, not constructors, on such classes"],"tags":["quarkus","cache","build-time","constructor","cdi"],"backgroundTag":"missing-default-constructor","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}