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

  1. Ensure the class declaring the advice method is annotated @Aspect (or a superclass is).
  2. 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.
  3. Verify the @Aspect annotation is on the classpath and visible to the context's classloader.
  4. 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

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


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)