{"record":{"id":"2fd2e51b617d9020","repo":"quarkusio/quarkus","slug":"target-roles-for-role-s-must-not-be-empty","errorCode":null,"errorMessage":"Target roles for role '%s' must not be empty","messagePattern":"Target roles for role '(.+?)' must not be empty","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java","lineNumber":248,"sourceCode":"        return path(paths).methods(\"DELETE\");\n    }\n\n    @Override\n    public HttpSecurity rolesMapping(Map<String, List<String>> roleToRoles) {\n        if (rolesMapping != null) {\n            throw new IllegalStateException(\"Roles mapping is already configured\");\n        }\n        if (roleToRoles == null || roleToRoles.isEmpty()) {\n            throw new IllegalArgumentException(\"Roles must not be empty\");\n        }\n        roleToRoles.forEach(new BiConsumer<String, List<String>>() {\n            @Override\n            public void accept(String sourceRole, List<String> targetRoles) {\n                if (sourceRole.isEmpty()) {\n                    throw new IllegalArgumentException(\"Source role must not be empty\");\n                }\n                if (targetRoles == null || targetRoles.isEmpty()) {\n                    throw new IllegalArgumentException(\"Target roles for role '%s' must not be empty\".formatted(sourceRole));\n                }\n            }\n        });\n\n        this.rolesMapping = RolesMapping.of(roleToRoles);\n        return this;\n    }\n\n    @Override\n    public HttpSecurity rolesMapping(String sourceRole, List<String> targetRoles) {\n        if (sourceRole == null) {\n            throw new IllegalArgumentException(\"Source role must not be null\");\n        }\n        if (targetRoles == null) {\n            throw new IllegalArgumentException(\"Target roles for role '%s' must not be null\".formatted(sourceRole));\n        }\n        return rolesMapping(Map.of(sourceRole, targetRoles));\n    }","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java#L230-L266","documentation":"The per-entry BiConsumer in rolesMapping(Map) also rejects entries whose target-roles list is null or empty, using a formatted message that names the offending source role. Target roles are the roles granted to identities holding the source role; an entry with no targets is meaningless and would produce a dead policy, so the library fails fast during RolesMapping.of preparation.","triggerScenarios":"rolesMapping(Map.of(\"user\", List.of())) or rolesMapping(\"user\", null) delegated through Map.of(\"user\", null) (note Map.of itself would NPE on a null value, so null lists typically arrive via HashMap); building lists dynamically where an empty list remained after filtering.","commonSituations":"Assembling target roles from config where an optional roles list was absent; stripping roles the application does not recognize and ending up with an empty list; JDBC/JSON-driven mappings with an empty targets array.","solutions":["Ensure every entry in the map has at least one target role before calling rolesMapping; drop entries with null/empty targets.","If the target list is derived from config, skip the whole entry (or the whole call) when the list resolves to empty.","Fix the data source so the source role has an explicit, non-empty list of target roles."],"exampleFix":"// before\nmapping.put(\"user\", filteredRoles); // filteredRoles may be empty\nhttpSecurity.rolesMapping(mapping);\n// after\nif (!filteredRoles.isEmpty()) {\n    mapping.put(\"user\", filteredRoles);\n}\nif (!mapping.isEmpty()) {\n    httpSecurity.rolesMapping(mapping);\n}","handlingStrategy":"validation","validationCode":"boolean validTargets = roleToRoles.values().stream()\n    .allMatch(v -> v != null && !v.isEmpty());\nif (validTargets) {\n    httpSecurity.rolesMapping(roleToRoles);\n}","typeGuard":"static boolean hasTargets(Map.Entry<String, List<String>> e) {\n    return e.getValue() != null && !e.getValue().isEmpty();\n}","tryCatchPattern":"try {\n    httpSecurity.rolesMapping(mapping);\n} catch (IllegalArgumentException e) {\n    // message names the offending source role\n    log.error(\"Role mapping rejected: \" + e.getMessage());\n}","preventionTips":["Drop entries whose target list is null/empty before registering the mapping.","When filtering target roles, remove the whole entry if the result is empty.","Validate data-driven mappings (JSON/DB) at load time."],"tags":["quarkus","http-security","role-mapping","argument-validation"],"backgroundTag":"empty-argument-validation","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"}