{"record":{"id":"b4c3b1135561ff59","repo":"quarkusio/quarkus","slug":"currently-only-entities-with-the-id-or-embeddedi","errorCode":null,"errorMessage":"Currently only Entities with the @Id or @EmbeddedId annotation are supported. Offending class is ${entity}","messagePattern":"Currently only Entities with the @Id or @EmbeddedId annotation are supported\\. Offending class is (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/StockMethodsAdder.java","lineNumber":1223,"sourceCode":"\n    private AnnotationTarget getIdAnnotationTarget(DotName entityDotName, IndexView index) {\n        return getIdAnnotationTargetRec(entityDotName, index, entityDotName);\n    }\n\n    private AnnotationTarget getIdAnnotationTargetRec(DotName currentDotName, IndexView index, DotName originalEntityDotName) {\n        ClassInfo classInfo = index.getClassByName(currentDotName);\n        if (classInfo == null) {\n            throw new IllegalStateException(\"Entity \" + originalEntityDotName + \" was not part of the Quarkus index\");\n        }\n\n        List<AnnotationInstance> annotationInstances = Stream.of(DotNames.JPA_ID, DotNames.JPA_EMBEDDED_ID)\n                .map(classInfo.annotationsMap()::get)\n                .filter(Objects::nonNull)\n                .flatMap(List::stream)\n                .collect(Collectors.toList());\n        if (annotationInstances.isEmpty()) {\n            if (DotNames.OBJECT.equals(classInfo.superName())) {\n                throw new IllegalArgumentException(\n                        \"Currently only Entities with the @Id or @EmbeddedId annotation are supported. Offending class is \"\n                                + originalEntityDotName);\n            }\n            return getIdAnnotationTargetRec(classInfo.superName(), index, originalEntityDotName);\n        }\n\n        if (annotationInstances.size() > 1) {\n            throw new IllegalArgumentException(\n                    \"Currently the @Id or @EmbeddedId annotation can only be placed on a single field or method. \" +\n                            \"Offending class is \" + originalEntityDotName);\n        }\n\n        return annotationInstances.get(0).target();\n    }\n\n    private Optional<AnnotationTarget> getVersionAnnotationTarget(DotName entityDotName, IndexView index) {\n        return getVersionAnnotationTargetRec(entityDotName, index, entityDotName);\n    }","sourceCodeStart":1205,"sourceCodeEnd":1241,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/StockMethodsAdder.java#L1205-L1241","documentation":"The Spring Data JPA extension requires every repository entity to expose an identifier annotated with @Id or @EmbeddedId so it can generate save/finder implementations. If neither annotation is found on the entity nor any of its superclasses (i.e., the hierarchy bottoms out at java.lang.Object without an id annotation), the build fails with this IllegalArgumentException.","triggerScenarios":"An entity class reachable from a Spring Data repository has no @Id or @EmbeddedId on any field or getter anywhere in its class hierarchy; the id annotation is a custom/non-JPA annotation the extension doesn't recognize.","commonSituations":"Using a custom @Key or Lombok-only id; forgetting @Id after copying an entity; using jakarta.persistence vs javax.persistence mismatch so the annotation isn't the JPA one the extension looks up.","solutions":["Annotate the identifier field or getter with jakarta.persistence.@Id (or @EmbeddedId for embedded ids)","If the id lives in a superclass, ensure the superclass is actually in the hierarchy being compiled (right import/dependency)","Verify the annotation import is jakarta.persistence.Id, not a similarly named custom annotation","For composite keys, use @EmbeddedId with an @Embeddable key class"],"exampleFix":"// before\n@Entity\npublic class User {\n    private Long id; // no annotation\n}\n\n// after\n@Entity\npublic class User {\n    @Id\n    private Long id;\n}","handlingStrategy":"validation","validationCode":"// Pre-check in a unit test:\nassertTrue(java.lang.reflect.Field.class.isAssignableFrom(User.class.getDeclaredFields().length > 0\n    && java.util.Arrays.stream(User.class.getDeclaredFields())\n        .anyMatch(f -> f.isAnnotationPresent(jakarta.persistence.Id.class)\n            || f.isAnnotationPresent(jakarta.persistence.EmbeddedId.class)));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always annotate exactly one id per entity using jakarta.persistence.@Id or @EmbeddedId","Add an architecture test (ArchUnit) asserting every @Entity has an @Id","Avoid custom id annotations in Spring Data repositories","Review entity imports after jakarta migration"],"tags":["quarkus","spring-data-jpa","jpa","entity-mapping","build-time"],"backgroundTag":"missing-jpa-id-annotation","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"}