{"record":{"id":"ef851ae72bf147d3","repo":"quarkusio/quarkus","slug":"has-to-be-an-interface-ef851a","errorCode":null,"errorMessage":" has to be an interface","messagePattern":" has to be an interface","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/MongoPanacheRestProcessor.java","lineNumber":138,"sourceCode":"            DataAccessImplementor dataAccessImplementor = new RepositoryDataAccessImplementor(repositoryClassName);\n            String resourceClass = resourceImplementor.implement(\n                    classOutput, dataAccessImplementor, resourceInterface, entityType);\n            unremovableBeansProducer.produce(new UnremovableBeanBuildItem(\n                    new UnremovableBeanBuildItem.BeanClassNameExclusion(repositoryClassName)));\n\n            restDataResourceProducer.produce(new RestDataResourceBuildItem(\n                    new ResourceMetadata(resourceClass, resourceInterface, entityType, idType,\n                            getEntityFields(index.getIndex(), entityType))));\n            if (capabilities.isPresent(Capability.RESTEASY)) {\n                bytecodeTransformersProducer.produce(\n                        getEntityIdAnnotationTransformer(entityType, entityClassHelper.getIdField(entityType).name()));\n            }\n        }\n    }\n\n    private void validateResource(IndexView index, ClassInfo classInfo) {\n        if (!Modifier.isInterface(classInfo.flags())) {\n            throw new RuntimeException(classInfo.name() + \" has to be an interface\");\n        }\n\n        if (classInfo.interfaceNames().size() > 1) {\n            throw new RuntimeException(classInfo.name() + \" should only extend REST Data Panache interface\");\n        }\n\n        if (!index.getKnownDirectImplementors(classInfo.name()).isEmpty()) {\n            throw new RuntimeException(classInfo.name() + \" should not be extended or implemented\");\n        }\n    }\n\n    private List<Type> getGenericTypes(ClassInfo classInfo) {\n        return classInfo.interfaceTypes()\n                .stream()\n                .findFirst()\n                .orElseThrow(() -> new RuntimeException(classInfo.toString() + \" does not have generic types\"))\n                .asParameterizedType()\n                .arguments();","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/panache/mongodb-rest-data-panache/deployment/src/main/java/io/quarkus/mongodb/rest/data/panache/deployment/MongoPanacheRestProcessor.java#L120-L156","documentation":"The MongoPanacheRestProcessor validates at build time that each detected REST data resource is an interface. Passing a concrete class (annotated to be treated as a resource) throws RuntimeException '<class> has to be an interface'.","triggerScenarios":"Annotating a concrete class (not an interface) with the REST Data Panache resource annotation so the build-step processor picks it up in findEntityResources/findRepositoryResources.","commonSituations":"Misreading the REST Data Panache model: resources must be interfaces extending PanacheMongoEntityBase-style resource contracts, while the entity itself is a separate class.","solutions":["Convert the resource to an interface that extends the appropriate REST Data Panache interface (e.g. PanacheMongoRepositoryResource).","Move the annotation from the entity class to a dedicated resource interface.","Remove the annotation if a REST resource was not intended."],"exampleFix":"// before\n@PanacheMongoResource\npublic class BookResource { ... } // concrete class\n// after\n@PanacheMongoResource\npublic interface BookResource extends PanacheMongoRepositoryResource<Book, ObjectId> {}\n","handlingStrategy":"validation","validationCode":"if (!resource.isInterface()) throw new IllegalArgumentException(\"@PanacheMongoResource target must be an interface: \" + resource.getName());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember REST Data Panache resources are interfaces, not classes.","Keep the entity class and the resource interface separate.","Validate with a quick compile: 'interface X extends PanacheMongoRepositoryResource<E, ID>'."],"tags":["mongodb","rest-data-panache","build-time","interface"],"backgroundTag":"rest-data-resource-not-interface","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"}