{"record":{"id":"d4e8be34e212fd4c","repo":"quarkusio/quarkus","slug":"you-can-only-annotate-one-class-with-userdefiniti","errorCode":null,"errorMessage":"You can only annotate one class with @UserDefinition","messagePattern":"You can only annotate one class with @UserDefinition","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/security-jpa-common/deployment/src/main/java/io/quarkus/security/jpa/common/deployment/QuarkusSecurityJpaCommonProcessor.java","lineNumber":34,"sourceCode":"import io.quarkus.security.jpa.Roles;\nimport io.quarkus.security.jpa.UserDefinition;\nimport io.quarkus.security.jpa.Username;\n\nclass QuarkusSecurityJpaCommonProcessor {\n\n    private static final DotName DOTNAME_USER_DEFINITION = DotName.createSimple(UserDefinition.class.getName());\n    private static final DotName DOTNAME_USERNAME = DotName.createSimple(Username.class.getName());\n    private static final DotName DOTNAME_ROLES = DotName.createSimple(Roles.class.getName());\n    static final DotName DOTNAME_PASSWORD = DotName.createSimple(Password.class.getName());\n\n    @BuildStep\n    void provideJpaSecurityDefinition(ApplicationIndexBuildItem index, PanacheEntityPredicateBuildItem panacheEntityPredicate,\n            BuildProducer<JpaSecurityDefinitionBuildItem> producer) {\n\n        // Generate an IdentityProvider if we have a @UserDefinition\n        List<AnnotationInstance> userDefinitions = index.getIndex().getAnnotations(DOTNAME_USER_DEFINITION);\n        if (userDefinitions.size() > 1) {\n            throw new RuntimeException(\"You can only annotate one class with @UserDefinition\");\n        } else if (!userDefinitions.isEmpty()) {\n            ClassInfo userDefinitionClass = userDefinitions.get(0).target().asClass();\n            AnnotationTarget annotatedUsername = getSingleAnnotatedElement(index.getIndex(), DOTNAME_USERNAME);\n            AnnotationTarget annotatedPassword = getSingleAnnotatedElement(index.getIndex(), DOTNAME_PASSWORD);\n            AnnotationTarget annotatedRoles = getSingleAnnotatedElement(index.getIndex(), DOTNAME_ROLES);\n            // collect associated getters if required\n            JpaSecurityDefinition jpaSecurityDefinition = new JpaSecurityDefinition(index.getIndex(),\n                    userDefinitionClass,\n                    panacheEntityPredicate.isPanache(userDefinitionClass),\n                    annotatedUsername,\n                    annotatedPassword,\n                    annotatedRoles);\n            producer.produce(new JpaSecurityDefinitionBuildItem(jpaSecurityDefinition));\n        }\n    }\n\n}\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security-jpa-common/deployment/src/main/java/io/quarkus/security/jpa/common/deployment/QuarkusSecurityJpaCommonProcessor.java#L16-L52","documentation":"The security-jpa build step only supports a single @UserDefinition-annotated class per application: it generates one identity provider from that entity. If the Jandex index contains more than one @UserDefinition class, provideJpaSecurityDefinition throws at build time.","triggerScenarios":"Annotating two or more entity classes with @io.quarkus.security.jpa.UserDefinition and building the application.","commonSituations":"Adding a second user entity for a new user type without realizing only one is supported; copying an example entity into a test/multi-module app where both end up in the application index; keeping an old @UserDefinition class after introducing a new one.","solutions":["Keep exactly one @UserDefinition class; remove @UserDefinition from the others (plain @Entity is fine).","Merge the two user entities into one with a role/type discriminator if both represent users.","Move the second user definition into a separate library/module not on the application index, or delete dead entities."],"exampleFix":"// before\n@UserDefinition @Entity public class User { ... }\n@UserDefinition @Entity public class Admin { ... }\n\n// after\n@UserDefinition @Entity public class User { ... }\n@Entity public class Admin { ... }","handlingStrategy":"validation","validationCode":"long n = allEntities.stream()\n    .filter(c -> c.isAnnotationPresent(UserDefinition.class))\n    .count();\nif (n > 1) throw new IllegalStateException(\"Only one @UserDefinition class is allowed\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Maintain a single @UserDefinition entity per application.","Grep for @UserDefinition before adding a new user entity.","Merge user variants into one entity with a discriminator."],"tags":["quarkus","security-jpa","build-time","duplicate-annotation"],"backgroundTag":"duplicate-annotation","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"}