spring-projects/spring-security · error · IllegalStateException
authorizationManagerFactory must be an instance of DefaultAu
Error message
authorizationManagerFactory must be an instance of DefaultAuthorizationManagerFactory
What it means
SecurityExpressionRoot keeps an AuthorizationManagerFactory; deprecated setters (setTrustResolver, setRoleHierarchy, setDefaultRolePrefix) still work by mutating the field only if it is a DefaultAuthorizationManagerFactory. If a custom AuthorizationManagerFactory was installed via setAuthorizationManagerFactory, calling these legacy setters throws IllegalStateException because the legacy mutation cannot be applied.
Source
Thrown at core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java:288
*/
public void setAuthorizationManagerFactory(AuthorizationManagerFactory<T> authorizationManagerFactory) {
Assert.notNull(authorizationManagerFactory, "authorizationManagerFactory cannot be null");
this.authorizationManagerFactory = authorizationManagerFactory;
}
/**
* Allows accessing the {@link DefaultAuthorizationManagerFactory} for getting and
* setting defaults. This method will be removed in Spring Security 8.
* @return the {@link DefaultAuthorizationManagerFactory}
* @throws IllegalStateException if a different {@link AuthorizationManagerFactory}
* was already set
* @deprecated Use
* {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
*/
@Deprecated(since = "7.0", forRemoval = true)
private DefaultAuthorizationManagerFactory<T> getDefaultAuthorizationManagerFactory() {
if (!(this.authorizationManagerFactory instanceof DefaultAuthorizationManagerFactory<T> defaultAuthorizationManagerFactory)) {
throw new IllegalStateException(
"authorizationManagerFactory must be an instance of DefaultAuthorizationManagerFactory");
}
return defaultAuthorizationManagerFactory;
}
@Override
public boolean hasPermission(Object target, Object permission) {
return this.permissionEvaluator.hasPermission(getAuthentication(), target, permission);
}
@Override
public boolean hasPermission(Object targetId, String targetType, Object permission) {
return this.permissionEvaluator.hasPermission(getAuthentication(), (Serializable) targetId, targetType,
permission);
}
public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {View on GitHub (pinned to 96852e8860)
Solutions
- Stop using the deprecated setters; configure role hierarchy via the AuthorizationManagerFactory instead
- Set the role hierarchy/prefix before any deprecated setter is called, or use DefaultAuthorizationManagerFactory explicitly
- Replace setRoleHierarchy(...) with RoleHierarchyAuthorityMappingStrategy wiring on the authorization manager
- Update custom code to use setAuthorizationManagerFactory(new DefaultAuthorizationManagerFactory<>()) configured with the desired prefix
Example fix
// before handler.setRoleHierarchy(roleHierarchy); handler.setAuthorizationManagerFactory(customFactory); // after DefaultAuthorizationManagerFactory<Object> factory = new DefaultAuthorizationManagerFactory<>(); factory.setRoleHierarchy(roleHierarchy); handler.setAuthorizationManagerFactory(factory);
Defensive patterns
Strategy: validation
Validate before calling
if (!(root.getAuthorizationManagerFactory() instanceof DefaultAuthorizationManagerFactory)) {
throw new IllegalStateException("Use setAuthorizationManagerFactory instead of deprecated setters");
} Type guard
if (factory instanceof DefaultAuthorizationManagerFactory<?> d) { d.setDefaultRolePrefix(prefix); } Try / catch
try { root.setDefaultRolePrefix("ROLE_"); }
catch (IllegalStateException e) { configureViaFactory(); } Prevention
- Treat @Deprecated(since="7.0") setters as removed in new code
- Configure role hierarchy/prefix on DefaultAuthorizationManagerFactory only
- Centralize security config in one class to avoid mixing legacy and new APIs
- Check Spring Security 7.0 migration guide before upgrading
When it happens
Trigger: Calling setDefaultRolePrefix, setTrustResolver, or setRoleHierarchy on a SecurityExpressionRoot (or handler configured with one) after replacing the authorizationManagerFactory with a non-default AuthorizationManagerFactory implementation.
Common situations: Migrating from Spring Security 5.x/6.x role-prefix/hierarchy setters to the 7.0 AuthorizationManagerFactory API; mixing deprecated configuration with new custom factory beans.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- One of the patterns in %s is missing a leading slash. This i
- It is not recommended to use authorizeRequests or FilterSecu
- Usage of authorizeRequests and FilterSecurityInterceptor are
- It is not recommended to use authorizeRequests or FilterSecu
- Usage of authorizeRequests and FilterSecurityInterceptor are
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/6e4b0c6b839b4541.
Report an issue: GitHub.