{"record":{"id":"7b14fb8d8608a33a","repo":"quarkusio/quarkus","slug":"policy-has-already-been-set","errorCode":null,"errorMessage":"Policy has already been set","messagePattern":"Policy has already been set","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":364,"sourceCode":"        @Override\n        public HttpSecurity policy(Predicate<SecurityIdentity> predicate) {\n            return policy((identity, request) -> !identity.isAnonymous() && predicate.test(identity));\n        }\n\n        @Override\n        public HttpSecurity policy(BiPredicate<SecurityIdentity, RoutingContext> predicate) {\n            return policy(new SimpleHttpSecurityPolicy(predicate));\n        }\n\n        private HttpSecurity authenticated() {\n            validatePolicyNotSetYet();\n            this.policy = new Policy(AuthenticatedHttpSecurityPolicy.NAME, null);\n            return HttpSecurityImpl.this;\n        }\n\n        private void validatePolicyNotSetYet() {\n            if (policy != null) {\n                throw new IllegalArgumentException(\"Policy has already been set\");\n            }\n        }\n    }\n\n    private final class HttpPermissionImpl implements HttpPermission, HttpPermissionCarrier {\n\n        private final String[] paths;\n        private boolean shared;\n        private boolean applyToJaxRs;\n        private String[] methods;\n        private HttpSecurityConfiguration.AuthenticationMechanisms authMechanism;\n        private AuthorizationPolicy authorizationPolicy;\n\n        private HttpPermissionImpl(String[] paths) {\n            this.paths = Arrays.copyOf(paths, paths.length);\n            this.authMechanism = null;\n            this.authorizationPolicy = null;\n            this.shared = false;","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java#L346-L382","documentation":"Thrown by HttpSecurityImpl's nested HttpPermission builder when a policy-defining method (permit, deny, roles, permissions, policy, authenticated) is called after a policy has already been assigned to this permission. Each HttpPermission can carry exactly one authorization policy, so a second call makes the configuration ambiguous and the builder fails fast with IllegalArgumentException.","triggerScenarios":"Calling two policy methods on the same HttpPermission instance, e.g. chaining .permit().deny(), .roles(\"admin\").permissions(\"read\"), or .authenticated().permit() on the same object returned from httpSecurity.paths(\"/x\").","commonSituations":"Reusing a captured HttpPermission variable to build several different rules; copy-pasted fluent chains where an extra policy call was left in; refactors that split one chain into two without creating a new permission via paths().","solutions":["Remove the duplicate policy call so each HttpPermission has exactly one of permit/deny/roles/permissions/policy/authenticated.","Create a fresh HttpPermission via HttpSecurity.paths(...) for each distinct rule instead of reusing one instance.","If combining behavior is intended, use the policy(...) API once with a composed HttpSecurityPolicy."],"exampleFix":"// before\nvar perm = httpSecurity.paths(\"/api/*\");\nperm.permit();\nperm.deny(); // IllegalArgumentException\n// after\nhttpSecurity.paths(\"/api/*\").permit();\nhttpSecurity.paths(\"/api/admin/*\").deny();","handlingStrategy":"validation","validationCode":"if (perm.isPolicySet()) throw new IllegalStateException(\"policy already assigned to this permission\");","typeGuard":null,"tryCatchPattern":"try { perm.permit(); } catch (IllegalArgumentException e) { if (!e.getMessage().contains(\"Policy has already been set\")) throw e; }","preventionTips":["One terminal policy call per paths(...) chain.","Never store and reuse HttpPermission instances across rules.","Build each rule as a single fluent expression from httpSecurity.paths(...)."],"tags":["quarkus","http-security","fluent-builder","illegal-argument"],"backgroundTag":"builder-state-already-set","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"}