{"record":{"id":"deab283e533dfc8f","repo":"quarkusio/quarkus","slug":"source-role-must-not-be-empty","errorCode":null,"errorMessage":"Source role must not be empty","messagePattern":"Source 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":245,"sourceCode":"\n    @Override\n    public HttpPermission delete(String... paths) {\n        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));","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java#L227-L263","documentation":"Inside HttpSecurityImpl.rolesMapping(Map), each map entry is validated by the anonymous BiConsumer; a source role that is the empty string (\"\") is rejected with IllegalArgumentException. A source role names the role the incoming identity must hold, so an empty name cannot be matched against any identity. The check runs per entry during forEach, before RolesMapping.of is built.","triggerScenarios":"rolesMapping(Map.of(\"\", List.of(\"admin\"))); building the map from split config strings where an empty key survived (e.g. \"=admin\" in a property value); a data-driven mapping file containing a blank role name.","commonSituations":"Parsing role mappings from application.properties where the key before '=' was omitted; user-supplied mapping files with blank lines parsed into empty keys; case-splitting a composite key like \"source:target\" where the source portion was empty.","solutions":["Remove empty-string keys from the map before calling rolesMapping (filter entries with !sourceRole.isBlank()).","Fix the config/data source so the source role name is present (e.g. correct the property key in application.properties).","Add your own up-front validation to fail with a clearer message naming where the blank role came from."],"exampleFix":"// before\nMap<String, List<String>> mapping = parse(rawMappings); // may contain \"\"\nhttpSecurity.rolesMapping(mapping);\n// after\nMap<String, List<String>> mapping = rawMappings.entrySet().stream()\n    .filter(e -> !e.getKey().isBlank())\n    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));\nhttpSecurity.rolesMapping(mapping);","handlingStrategy":"validation","validationCode":"boolean allRolesNamed = roleToRoles.keySet().stream().noneMatch(k -> k.isBlank());\nif (allRolesNamed) {\n    httpSecurity.rolesMapping(roleToRoles);\n}","typeGuard":"static boolean isValidRoleMapping(Map<String, List<String>> m) {\n    return m != null && m.entrySet().stream().allMatch(e ->\n        e.getKey() != null && !e.getKey().isBlank()\n        && e.getValue() != null && !e.getValue().isEmpty());\n}","tryCatchPattern":"try {\n    httpSecurity.rolesMapping(mapping);\n} catch (IllegalArgumentException e) {\n    throw new ConfigurationException(\"Invalid source role in mapping: \" + e.getMessage(), e);\n}","preventionTips":["Trim and validate role names when parsing them from properties or files.","Filter out blank keys before building the mapping map.","Log dropped entries so silently removed blank roles are visible."],"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-12T22:17:10.623Z"}