quarkusio/quarkus · error · RuntimeException

Unable to load class '%s' for creating permission

Error message

Unable to load class '%s' for creating permission

What it means

SecurityCheckRecorder.loadClass() loads a permission class by name via the thread contextClassLoader at runtime. If the class is not found it wraps the ClassNotFoundException in a RuntimeException. This happens during recording/registration of permission-based security checks when a configured permission class name cannot be resolved.

Source

Thrown at extensions/security/runtime/src/main/java/io/quarkus/security/runtime/SecurityCheckRecorder.java:373

    public SecurityCheckStorage create(RuntimeValue<SecurityCheckStorageBuilder> builder) {
        return builder.getValue().create();
    }

    public void resolveRolesAllowedConfigExpRoles() {
        if (!configExpRolesAllowedChecks.isEmpty()) {
            for (SupplierRolesAllowedCheck configExpRolesAllowedCheck : configExpRolesAllowedChecks) {
                configExpRolesAllowedCheck.resolveAllowedRoles();
            }
            configExpRolesAllowedChecks.clear();
        }
    }

    private Class<?> loadClass(String className) {
        try {
            return Thread.currentThread().getContextClassLoader().loadClass(className);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Unable to load class '" + className + "' for creating permission", e);
        }
    }

    public void registerDefaultSecurityCheck(RuntimeValue<SecurityCheckStorageBuilder> builder, SecurityCheck securityCheck) {
        builder.getValue().registerDefaultSecurityCheck(securityCheck);
    }

    public Supplier<SecurityConstrainer> createSecurityConstrainer(Supplier<Map<String, Object>> additionalEventPropsSupplier) {
        return new Supplier<SecurityConstrainer>() {
            @Override
            public SecurityConstrainer get() {
                var container = Arc.container();
                var beanManager = container.beanManager();
                var eventPropsSupplier = additionalEventPropsSupplier == null ? new Supplier<Map<String, Object>>() {
                    @Override
                    public Map<String, Object> get() {
                        return Map.of();
                    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Fix the fully-qualified class name in config or annotation — verify spelling and package.
  2. Add the dependency containing the Permission class to the runtime (non-test, non-optional) scope.
  3. Rebuild the application after adding the dependency so the class is packaged.
  4. If using Quarkus, ensure the class is not in a deployment-only module; runtime classes must be in a runtime artifact.

Example fix

// before (application.properties)
quarkus.security.permissions.perm1.class=com.acme.security.MyPermisson
// after (typo fixed)
quarkus.security.permissions.perm1.class=com.acme.security.MyPermission
Defensive patterns

Strategy: validation

Validate before calling

try {
    Class.forName("com.acme.security.MyPermission", false,
        Thread.currentThread().getContextClassLoader());
} catch (ClassNotFoundException e) {
    throw new IllegalStateException("Permission class missing from runtime classpath", e);
}

Try / catch

try {
    securedService.invoke();
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("Unable to load class")) {
        log.error("Check quarkus.security.permissions.* class names and dependencies", e);
    }
}

Prevention

When it happens

Trigger: quarkus.security.permissions.<name>.class or a @PermissionsAllowed permission class name refers to a class missing from the runtime application classpath, or a typo in the fully-qualified name.

Common situations: Typo in fully-qualified class name in configuration; permission class lives in a module/dependency not included in the build; class renamed after a refactor or version upgrade; class only present in a test scope dependency.

Related errors


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