{"record":{"id":"edc6d79a961ae0dc","repo":"quarkusio/quarkus","slug":"missing-rolevalue-annotation-on-non-string-role","errorCode":null,"errorMessage":"Missing @RoleValue annotation on (non-String) role element type: ${elementType}","messagePattern":"Missing @RoleValue annotation on \\(non-String\\) role element type: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/security-jpa-common/deployment/src/main/java/io/quarkus/security/jpa/common/deployment/JpaSecurityIdentityUtil.java","lineNumber":178,"sourceCode":"                break;\n            case PARAMETERIZED_TYPE:\n                DotName roleType = rolesType.name();\n                if (roleType.equals(DotNames.LIST)\n                        || roleType.equals(DOTNAME_COLLECTION)\n                        || roleType.equals(DOTNAME_SET)) {\n                    Type elementType = rolesType.asParameterizedType().arguments().get(0);\n                    JpaSecurityDefinition.FieldOrMethod rolesFieldOrMethod;\n                    if (!elementType.name().equals(DotNames.STRING)) {\n                        ClassInfo roleClass = index.getClassByName(elementType.name());\n                        if (roleClass == null) {\n                            throw new RuntimeException(\n                                    \"The role element type must be indexed by Jandex: \" + elementType);\n                        }\n                        AnnotationTarget annotatedRolesValue = getSingleAnnotatedElement(index, DOTNAME_ROLES_VALUE);\n                        rolesFieldOrMethod = JpaSecurityDefinition.getFieldOrMethod(index, roleClass,\n                                annotatedRolesValue, panacheEntityPredicate.isPanache(roleClass));\n                        if (rolesFieldOrMethod == null) {\n                            throw new RuntimeException(\n                                    \"Missing @RoleValue annotation on (non-String) role element type: \" + elementType);\n                        }\n                    } else {\n                        rolesFieldOrMethod = null;\n                    }\n                    // for(:elementType roleElement : :role){\n                    //    JpaIdentityProviderUtil.addRoles(:role.roleField);\n                    //    // or for String collections:\n                    //    JpaIdentityProviderUtil.addRoles(:role);\n                    // }\n                    bc.forEach(role, (loopBody, var) -> {\n                        Expr roleElement;\n                        if (rolesFieldOrMethod != null) {\n                            roleElement = rolesFieldOrMethod.readValue(loopBody, var);\n                        } else {\n                            roleElement = var;\n                        }\n                        loopBody.invokeStatic(","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security-jpa-common/deployment/src/main/java/io/quarkus/security/jpa/common/deployment/JpaSecurityIdentityUtil.java#L160-L196","documentation":"For a non-String role element type (e.g. List<RoleEntity>), the generator needs a member of the role class annotated with @RoleValue to know which field/method yields the role name string. If no such annotated member exists (or it is ambiguous/unresolvable), the build fails.","triggerScenarios":"Declaring @Roles on a List/Set/Collection of a custom role entity class that has no field or getter annotated with @io.quarkus.security.jpa.RolesValue.","commonSituations":"Role entity written without @RoleValue because roles were previously Strings and then refactored to an entity; annotation placed on the user entity instead of the role entity; @RoleValue accidentally on multiple members (which trips the sibling single-annotation error instead).","solutions":["Annotate exactly one field or getter of the role entity class with @RoleValue (e.g. the role name String).","Alternatively, revert the @Roles field to a plain String or List<String>.","Verify the @RoleValue annotation is io.quarkus.security.jpa.RolesValue and applied to a readable field/getter of the role class."],"exampleFix":"// before\npublic class Role { private String name; }\n\n// after\npublic class Role {\n    @RoleValue\n    public String getName() { return name; }\n}","handlingStrategy":"validation","validationCode":"boolean hasRoleValue = Arrays.stream(Role.class.getDeclaredMethods())\n    .anyMatch(m -> m.isAnnotationPresent(RolesValue.class))\n    || Arrays.stream(Role.class.getDeclaredFields())\n    .anyMatch(f -> f.isAnnotationPresent(RolesValue.class));\nif (!hasRoleValue) throw new IllegalStateException(\"Role entity needs exactly one @RoleValue member\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always add @RoleValue to the role-name getter when using entity-typed roles.","Place @RoleValue on exactly one member of the role class.","Keep role-name members public or getter-accessible."],"tags":["quarkus","security-jpa","build-time","annotation-missing"],"backgroundTag":"missing-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"}