quarkusio/quarkus · error · IllegalArgumentException

HttpSecurityPolicy must not be null

Error message

HttpSecurityPolicy must not be null

What it means

The PathPolicy's policy(HttpSecurityPolicy) method rejects a null policy argument with IllegalArgumentException. This is the generic escape hatch of the HttpSecurity DSL allowing any custom HttpSecurityPolicy implementation to be attached to a path; because the surrounding Policy holder cannot represent 'no policy', a null argument would corrupt the builder state, so it is validated immediately after validatePolicyNotSetYet().

Source

Thrown at extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/security/HttpSecurityImpl.java:340

            policy = new Policy(null, new PermissionsHttpSecurityPolicy(permissions));
            return HttpSecurityImpl.this;
        }

        @Override
        public HttpSecurity permissions(String... permissionNames) {
            Objects.requireNonNull(permissionNames);
            StringPermission[] stringPermissions = new StringPermission[permissionNames.length];
            for (int i = 0; i < permissionNames.length; i++) {
                stringPermissions[i] = new StringPermission(permissionNames[i]);
            }
            return permissions(stringPermissions);
        }

        @Override
        public HttpSecurity policy(HttpSecurityPolicy httpSecurityPolicy) {
            validatePolicyNotSetYet();
            if (httpSecurityPolicy == null) {
                throw new IllegalArgumentException("HttpSecurityPolicy must not be null");
            }
            this.policy = new Policy(null, httpSecurityPolicy);
            return HttpSecurityImpl.this;
        }

        @Override
        public HttpSecurity policy(Predicate<SecurityIdentity> predicate) {
            return policy((identity, request) -> !identity.isAnonymous() && predicate.test(identity));
        }

        @Override
        public HttpSecurity policy(BiPredicate<SecurityIdentity, RoutingContext> predicate) {
            return policy(new SimpleHttpSecurityPolicy(predicate));
        }

        private HttpSecurity authenticated() {
            validatePolicyNotSetYet();
            this.policy = new Policy(AuthenticatedHttpSecurityPolicy.NAME, null);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure a concrete HttpSecurityPolicy instance is constructed or injected before calling policy(...).
  2. Skip the policy(...) call when no custom policy is available and rely on the default security behavior.
  3. If the policy comes from CDI, verify the bean exists (correct qualifiers/scope) so the lookup does not return null.

Example fix

// before
HttpSecurityPolicy custom = lookupPolicy(); // may be null
httpSecurity.path("/api/*").policy(custom);
// after
HttpSecurityPolicy custom = lookupPolicy();
if (custom != null) {
    httpSecurity.path("/api/*").policy(custom);
}
Defensive patterns

Strategy: validation

Validate before calling

if (customPolicy != null) {
    httpSecurity.path(path).policy(customPolicy);
}

Type guard

static boolean hasPolicy(HttpSecurityPolicy p) {
    return p != null;
}

Try / catch

try {
    httpSecurity.path("/api/*").policy(customPolicy);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("Custom policy failed to resolve: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: httpSecurity.path("/x").policy(myPolicy) where myPolicy is an uninitialized field or a factory method returned null; a custom HttpSecurityPolicy bean that failed to resolve; supplying the result of an optional lookup without null handling.

Common situations: Plugging custom authorization logic into programmatic security where the policy instance is produced by CDI lookup or configuration that can be absent; test code with a not-yet-assigned policy field; refactors that replaced a concrete policy with a nullable supplier.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/783a11d220374c3c. Report an issue: GitHub.