{"record":{"id":"4ff2895d332d344d","repo":"quarkusio/quarkus","slug":"currently-expressions-containing-both-logical-and","errorCode":null,"errorMessage":"Currently expressions containing both logical 'and' / 'or' are not supported. Offending expression is <value>' in the @PreAuthorize annotation on method '<method>' of class '<class>","messagePattern":"Currently expressions containing both logical 'and' / 'or' are not supported\\. Offending expression is <value>' in the @PreAuthorize annotation on method '<method>' of class '<class>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/spring-security/deployment/src/main/java/io/quarkus/spring/security/deployment/SpringSecurityProcessor.java","lineNumber":427,"sourceCode":"            MethodInfo methodInfo = entry.getKey();\n            String value = instance.value().asString().trim();\n\n            /*\n             * TODO: this serves fine for most purposes but a full-blown solution will need a proper parser\n             */\n\n            boolean containsAnd = false;\n            boolean containsOr = false;\n            String lowercaseValue = value.toLowerCase();\n            if (lowercaseValue.contains(\" or \")) {\n                containsOr = true;\n            }\n            if (lowercaseValue.contains(\" and \")) {\n                containsAnd = true;\n            }\n\n            if (containsAnd && containsOr) {\n                throw new IllegalStateException(\n                        \"Currently expressions containing both logical 'and' / 'or' are not supported. Offending expression is \"\n                                + value + \"' in the @PreAuthorize annotation on method '\" + methodInfo.name()\n                                + \"' of class '\" + methodInfo.declaringClass());\n            }\n\n            String[] parts = { value };\n            if (containsAnd) {\n                parts = value.split(\"(?i) and \");\n            } else if (containsOr) {\n                parts = value.split(\"(?i) or \");\n            }\n\n            List<SecurityCheck> securityChecks = new ArrayList<>(parts.length);\n\n            for (String part : parts) {\n                part = part.trim();\n                if (part.equals(\"permitAll()\")) {\n                    securityChecks.add(securityCheckRecorder.permitAll());","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spring-security/deployment/src/main/java/io/quarkus/spring/security/deployment/SpringSecurityProcessor.java#L409-L445","documentation":"Quarkus's Spring Security expression subset cannot evaluate an expression containing both logical 'and' and 'or' operators. addSpringPreAuthorizeSecurityCheck detects both in the @PreAuthorize value and throws this IllegalStateException at build time. (Note the message has an unbalanced quote — cosmetic.)","triggerScenarios":"An expression like \"hasRole('admin') and hasRole('user') or isAuthenticated()\" — where the lowercased value contains both \" and \" and \" or \" — triggers the check.","commonSituations":"Porting complex Spring SpEL security rules unchanged; combining role checks with other conditions in one annotation; writing compound authorization rules.","solutions":["Split the logic: keep the simpler conditions in @PreAuthorize and move the compound decision into a public boolean bean method invoked as @PreAuthorize(\"@authz.canAccess(#x)\")","Use only 'and' or only 'or' in the expression if it can be restructured (single operator forms are supported)","Drop parentheses-dependent logic entirely and evaluate it in application code or a custom SecurityCheck"],"exampleFix":"// before\n@PreAuthorize(\"hasRole('admin') and #user == principalUsername or isAnonymous()\")\n\n// after\n@PreAuthorize(\"@authz.canAccess(#user)\") // public boolean canAccess(String user) { ... }","handlingStrategy":"validation","validationCode":"String v = \"hasRole('admin') and hasRole('user')\";\nString lc = v.toLowerCase();\nif (lc.contains(\" and \") && lc.contains(\" or \"))\n    throw new IllegalStateException(\"Both 'and' and 'or' unsupported: \" + v);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use only one logical operator per @PreAuthorize expression","Move compound boolean logic into a boolean bean method","Add a unit/arch test that scans @PreAuthorize values for mixed operators"],"tags":["spring-security","build-time","preauthorize","unsupported-expression"],"backgroundTag":"unsupported-preauthorize-operators","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"}