spring-projects/spring-security · error · AccessDeniedException
Access is denied
Error message
Access is denied
What it means
AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions() throws AccessDeniedException when every AccessDecisionVoter abstained and the 'allowIfAllAbstainDecisions' flag is false. Default security posture: abstention means deny.
Source
Thrown at access/src/main/java/org/springframework/security/access/vote/AbstractAccessDecisionManager.java:71
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private boolean allowIfAllAbstainDecisions = false;
protected AbstractAccessDecisionManager(List<AccessDecisionVoter<?>> decisionVoters) {
Assert.notEmpty(decisionVoters, "A list of AccessDecisionVoters is required");
this.decisionVoters = decisionVoters;
}
@Override
public void afterPropertiesSet() {
Assert.notEmpty(this.decisionVoters, "A list of AccessDecisionVoters is required");
Assert.notNull(this.messages, "A message source must be set");
}
protected final void checkAllowIfAllAbstainDecisions() {
if (!this.isAllowIfAllAbstainDecisions()) {
throw new AccessDeniedException(
this.messages.getMessage("AbstractAccessDecisionManager.accessDenied", "Access is denied"));
}
}
public List<AccessDecisionVoter<?>> getDecisionVoters() {
return this.decisionVoters;
}
public boolean isAllowIfAllAbstainDecisions() {
return this.allowIfAllAbstainDecisions;
}
public void setAllowIfAllAbstainDecisions(boolean allowIfAllAbstainDecisions) {
this.allowIfAllAbstainDecisions = allowIfAllAbstainDecisions;
}
@Override
public void setMessageSource(MessageSource messageSource) {View on GitHub (pinned to 96852e8860)
Solutions
- Set allowIfAllAbstainDecisions(true) on the decision manager if abstain should grant
- Fix voter configuration so the relevant attributes are actually voted on (check RolePrefix, supported attribute types)
- Ensure the secured invocation carries config attributes your voters understand
- Add or register the appropriate voters (RoleVoter, AuthenticatedVoter, etc.)
Example fix
// before AffirmativeBased am = new AffirmativeBased(voters); // abstentions denied // after AffirmativeBased am = new AffirmativeBased(voters); am.setAllowIfAllAbstainDecisions(true);
Defensive patterns
Strategy: validation
Validate before calling
if (voters.stream().noneMatch(v -> v.supports(configAttribute))) {
throw new IllegalStateException("No voter supports attribute " + configAttribute);
} Type guard
null
Try / catch
try {
decisionManager.decide(auth, object, attrs);
} catch (AccessDeniedException e) {
log.debug("All voters abstained and abstain-grant is disabled");
throw e;
} Prevention
- Check that every securing attribute is supported by at least one voter
- Explicitly set allowIfAllAbstainDecisions to document intent
- Keep voter lists non-empty and reviewed
When it happens
Trigger: decide() on AffirmativeBased/ConsensusBased/UnanimousBased completes with zero grant/deny votes and allowIfAllAbstainDecisions (default false) denies; e.g. no voter has a config attribute matching the secured method's attributes.
Common situations: Method security annotations whose attributes no voter recognizes (e.g. ROLE_ prefix mismatch, missing RoleVoter), empty voter list, or custom voter abstaining because ConfigAttribute is unsupported.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/c65d948cc16ddda8.
Report an issue: GitHub.