spring-projects/spring-framework · error · AopConfigException
Advice must be declared inside an aspect type: Offending…
Error message
Advice must be declared inside an aspect type: Offending method '{candidateAdviceMethod}' in class [{candidateAspectClass.getName()}] What it means
Thrown as an AopConfigException from ReflectiveAspectJAdvisorFactory.getAdvice() when an advice method (carrying @Before/@After/@Around/@AfterReturning/@AfterThrowing) is discovered but isAspect(candidateAspectClass) returns false. In other words, advice annotations exist on a method of a class that is not (or is no longer considered) an aspect. This commonly happens when the aspect class is ajc-compiled and the spring.aop.ajc.ignore flag is set, or when the @Aspect annotation is not visible to the isAspect check.
Solutions
- Ensure the class declaring the advice method is annotated @Aspect (or a superclass is).
- If spring.aop.ajc.ignore is set, restructure the AspectJ configuration so the ajc-compiled aspect is not also exposed to Spring AOP auto-proxying.
- Verify the @Aspect annotation is on the classpath and visible to the context's classloader.
- Move advice methods off non-aspect classes.
Example fix
// before (and -Dspring.aop.ajc.ignore=true)
public class AuditHandler {
@Before("execution(* com.example.*.*(..))")
public void audit() { ... }
}
// after
@Aspect
public class AuditHandler {
@Before("execution(* com.example.*.*(..))")
public void audit() { ... }
} Defensive patterns
Strategy: validation
Validate before calling
import org.springframework.aop.aspectj.annotation.AspectJAdvisorFactory;
public static boolean isAspectAndAdviceMethods(AspectJAdvisorFactory factory, Class<?> candidateAspectClass) {
return factory.isAspect(candidateAspectClass);
}
// before getAdvice/getAdvisors, ensure the class is recognized as an aspect:
if (!advisorFactory.isAspect(candidateAspectClass)) {
throw new IllegalStateException(candidateAspectClass + " is not an aspect; cannot process advice methods");
} Type guard
import org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory;
public static boolean isRecognizedAspect(Class<?> c) {
return new ReflectiveAspectJAdvisorFactory().isAspect(c);
} Try / catch
try {
Advice advice = advisorFactory.getAdvice(method, pointcut, factory, order, name);
} catch (AopConfigException ex) {
if (ex.getMessage().startsWith("Advice must be declared inside an aspect type")) {
// ensure @Aspect is present, or unset spring.aop.ajc.ignore
} else throw ex;
} Prevention
- Keep @Aspect on every class that declares advice methods.
- If enabling spring.aop.ajc.ignore=true, ensure ajc-compiled aspects are not also auto-proxied by Spring.
- Add a startup assertion that advisorFactory.isAspect(type) holds for all advice-bearing beans.
When it happens
Trigger: An advice method on a class without @Aspect reaching getAdvice(); an ajc-compiled aspect being processed by Spring AOP auto-proxy while spring.aop.ajc.ignore=true (isAspect returns false for ajc-compiled classes); a classloader/annotation-visibility issue making @Aspect invisible.
Common situations: Enabling spring.aop.ajc.ignore to avoid double-proxying but leaving advice methods on the ajc-compiled class; moving advice methods to a base class that lacks @Aspect; annotation retention or classloader issues; refactoring that removed @Aspect from a class still carrying advice annotations.
Related errors
- is not an @AspectJ aspect
- is not a valid AspectJ annotation
- 'argumentNames' property of AbstractAspectJAdvice contains…
- uses percflow instantiation model: This is not supported in…
- uses percflowbelow instantiation model: This is not…
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/dd0fba471ad12763.
Report an issue: GitHub.
Appendix: source
Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java:257
@Override
public @Nullable Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AspectJAnnotation aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut -> {
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
}
case AtAround -> springAdvice = new AspectJAroundAdvice(View on GitHub (pinned to 69bf83ad71)