spring-projects/spring-framework · error · AopConfigException
PerClause {} not supported by Spring AOP for {}
Error message
PerClause {} not supported by Spring AOP for {} What it means
Thrown by the AspectMetadata constructor's default switch branch when the aspect's per-clause kind is none of SINGLETON, PERTARGET, PERTHIS, or PERTYPEWITHIN — i.e. PERCFLOW or PERCFLOWBELOW. This is the AspectMetadata-side guard mirroring AbstractAspectJAdvisorFactory.validate(). It rejects control-flow-based instantiation models that Spring's proxy-based AOP cannot honor.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AspectMetadata.java:118
this.aspectClass = ajType.getJavaClass();
this.ajType = ajType;
switch (this.ajType.getPerClause().getKind()) {
case SINGLETON -> {
this.perClausePointcut = Pointcut.TRUE;
}
case PERTARGET, PERTHIS -> {
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
ajexp.setLocation(aspectClass.getName());
ajexp.setExpression(findPerClause(aspectClass));
ajexp.setPointcutDeclarationScope(aspectClass);
this.perClausePointcut = ajexp;
}
case PERTYPEWITHIN -> {
// Works with a type pattern
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
}
default -> throw new AopConfigException(
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
}
}
/**
* Extract contents from String of form {@code pertarget(contents)}.
*/
private String findPerClause(Class<?> aspectClass) {
Aspect ann = aspectClass.getAnnotation(Aspect.class);
if (ann == null) {
return "";
}
String value = ann.value();
int beginIndex = value.indexOf('(');
if (beginIndex < 0) {
return "";
}
return value.substring(beginIndex + 1, value.length() - 1);View on GitHub (pinned to e8729d0438)
Solutions
- Remove the percflow/percflowbelow per-clause so the aspect becomes a singleton.
- Switch to AspectJ compile-time or load-time weaving if control-flow scoping is required.
Example fix
// before
@Aspect("percflow(execution(* com.acme..*(..)))")
public class CflowAspect { ... }
// after
@Aspect
public class CflowAspect { ... } Defensive patterns
Strategy: validation
Validate before calling
import org.aspectj.lang.reflect.*;
void ensureSupportedPerClause(Class<?> c) {
PerClauseKind k = AjTypeSystem.getAjType(c).getPerClause().getKind();
if (k != PerClauseKind.SINGLETON && k != PerClauseKind.PERTARGET
&& k != PerClauseKind.PERTHIS && k != PerClauseKind.PERTYPEWITHIN)
throw new IllegalStateException("PerClause " + k + " not supported for " + c);
} Prevention
- Whitelist per-clauses to singleton/pertarget/perthis/pertypewithin for Spring AOP.
- Run a startup validation over all aspect beans.
When it happens
Trigger: Any aspect whose AjType per-clause resolves to PerClauseKind.PERCFLOW or PERCFLOWBELOW being processed through AspectMetadata construction (auto-proxy, AspectJProxyFactory, etc.).
Common situations: Using @Aspect("percflow(...)") or @Aspect("percflowbelow(...)") in a Spring AOP context. Same root cause as errors 40/41 but hit on a different code path.
Related errors
- {} uses percflow instantiation model: This is not supported
- {} uses percflowbelow instantiation model: This is not suppo
- MethodInvocation is not a Spring ProxyMethodInvocation: {}
- 'argumentNames' property of AbstractAspectJAdvice contains a
- Only afterReturning advice can be used to bind a return valu
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/d52168ba671a7cb3.json.
Report an issue: GitHub.