{"record":{"id":"b2c40c354da3aaa9","repo":"quarkusio/quarkus","slug":"class-s-was-annotated-with-permissionsallowed","errorCode":null,"errorMessage":"Class '%s' was annotated with '@PermissionsAllowed', but no valid permission was provided","messagePattern":"Class '(.+?)' was annotated with '@PermissionsAllowed', but no valid permission was provided","errorType":"exception","errorClass":"java.lang.RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java","lineNumber":640,"sourceCode":"                            final Set<String> actions = new HashSet<>();\n                            actions.add(action);\n                            permissionToActions.put(permissionNameKey, actions);\n                        }\n                    } else {\n                        if (!permissionToActions.containsKey(permissionNameKey)) {\n                            permissionToActions.put(permissionNameKey, new HashSet<>());\n                        }\n                    }\n                }\n            }\n\n            if (permissionToActions.isEmpty()) {\n                if (annotationTarget.kind() == AnnotationTarget.Kind.METHOD) {\n                    throw new RuntimeException(String.format(\n                            \"Method '%s' was annotated with '@PermissionsAllowed', but no valid permission was provided\",\n                            annotationTarget.asMethod().name()));\n                } else {\n                    throw new RuntimeException(String.format(\n                            \"Class '%s' was annotated with '@PermissionsAllowed', but no valid permission was provided\",\n                            annotationTarget.asClass().name()));\n                }\n            }\n\n            // permissions specified via @PermissionsAllowed has 'one of' relation, therefore we put them in one list\n            final List<PermissionKey> orPermissions = new ArrayList<>();\n            final String[] params = instance.value(\"params\") == null ? new String[] { PermissionsAllowed.AUTODETECTED }\n                    : instance.value(\"params\").asStringArray();\n            final Type classType = getPermissionClass(instance);\n            final boolean inclusive = instance.value(\"inclusive\") != null && instance.value(\"inclusive\").asBoolean();\n\n            if (inclusive && foundPermissionChecker) {\n                // @PermissionsAllowed({ \"read\", \"read:all\", \"read:it\", \"write\" } && @PermissionChecker(\"read\")\n                // require @PermissionChecker for all 'read:action' because determining expected behavior would be too\n                // complex; similarly for @PermissionChecker(\"read:all\") require 'read' and 'read:it' have checker as well\n                List<PermissionNameAndChecker> checkerPermissions = permissionToActions.keySet().stream()\n                        .filter(k -> k.checker != null).toList();","sourceCodeStart":622,"sourceCodeEnd":658,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/PermissionSecurityChecks.java#L622-L658","documentation":"Identical to the method-level variant, but thrown when the @PermissionsAllowed annotation target is a CLASS and no valid permission was provided. Quarkus rejects class-level annotations that restrict nothing, because applying security to all methods with zero permissions cannot be satisfied.","triggerScenarios":"Annotating a class with @PermissionsAllowed using an empty value array or values that all fail parsing, leaving permissionToActions empty for the class.","commonSituations":"Copy-pasted class-level annotation with placeholder values; constants array emptied by refactor; values relying on an unsupported expression form so everything is dropped.","solutions":["Add at least one valid permission to the class-level @PermissionsAllowed, e.g. @PermissionsAllowed(\"admin\").","Remove the annotation if class-wide permission enforcement is not intended.","If different permissions per method are needed, move @PermissionsAllowed from the class to individual methods."],"exampleFix":"// before\n@PermissionsAllowed({})\npublic class AdminService { ... }\n\n// after\n@PermissionsAllowed(\"admin\")\npublic class AdminService { ... }","handlingStrategy":"validation","validationCode":"// Class-level check: ensure the shared permission constant array is non-empty\nassert permissionValues != null && permissionValues.length > 0 : \"class-level @PermissionsAllowed needs values\";","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep class-level permission constants in one place and unit-test them.","Move annotations to methods when permissions differ per operation.","Review class-level security annotations in code review."],"tags":["quarkus","security","permissionsallowed","missing-permission"],"backgroundTag":"missing-permission","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"}