spring-projects/spring-framework · error · IllegalArgumentException

is not a valid AspectJ annotation

Error message

{annotation} is not a valid AspectJ annotation

What it means

Thrown as an IllegalArgumentException from the AspectJAnnotation constructor when an error occurs while resolving the pointcut expression string from a recognized AspectJ advice annotation (@Pointcut, @Before, @After, @Around, @AfterReturning, @AfterThrowing). The underlying cause (the original exception) is chained. It signals the annotation is structurally present but malformed enough that Spring cannot extract or interpret its pointcut/value attribute.

Solutions

  1. Inspect the chained cause exception (getCause()) to find the real reflective failure.
  2. Ensure the advice annotation is the standard AspectJ annotation and not a custom meta-annotation that interferes with the 'pointcut'/'value' attribute.
  3. Recompile the aspect class to rule out a stale/corrupt class file.
  4. Verify the annotation is not being synthesized by a library that breaks AnnotationUtils.getValue semantics.
Defensive patterns

Strategy: try-catch

Validate before calling

import org.springframework.core.annotation.AnnotationUtils;

public static boolean hasResolvablePointcut(java.lang.annotation.Annotation ann) {
    for (String attr : new String[]{"pointcut", "value"}) {
        Object v = AnnotationUtils.getValue(ann, attr);
        if (v instanceof String s && !s.isEmpty()) return true;
    }
    return false;
}

// validate advice annotations before registering the aspect:
for (Method m : aspectClass.getDeclaredMethods()) {
    for (var a : m.getAnnotations()) {
        if (isAspectJAdvice(a) && !hasResolvablePointcut(a)) {
            throw new IllegalStateException("Advice " + m + " has an unresolvable pointcut");
        }
    }
}

Try / catch

try {
    List<Advisor> advisors = advisorFactory.getAdvisors(factory);
} catch (IllegalArgumentException ex) {
    if (ex.getCause() != null && ex.getMessage().contains("not a valid AspectJ annotation")) {
        // log the offending annotation and cause, skip the aspect
    } else throw ex;
}

Prevention

When it happens

Trigger: An advice annotation whose 'pointcut' or 'value' attribute throws on reflective access (e.g., a custom meta-annotation that breaks AnnotationUtils.getValue), or whose attribute accessor misbehaves due to a classloader/annotation-proxy issue. This is reached only after findAspectJAnnotationOnMethod identifies the annotation as one of the six known AspectJ types.

Common situations: Custom meta-annotations wrapping @Around/@Before with unusual attribute merging; annotation proxied via a byte-code tool that does not honor the standard Annotation contract; a corrupt class file; JVM or annotation library version incompatibilities that affect reflective attribute reads.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/f4850e064f694a2d. Report an issue: GitHub.

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java:189

		private final Annotation annotation;

		private final AspectJAnnotationType annotationType;

		private final String pointcutExpression;

		private final String argumentNames;

		public AspectJAnnotation(Annotation annotation) {
			this.annotation = annotation;
			this.annotationType = determineAnnotationType(annotation);
			try {
				this.pointcutExpression = resolvePointcutExpression(annotation);
				Object argNames = AnnotationUtils.getValue(annotation, "argNames");
				this.argumentNames = (argNames instanceof String names ? names : "");
			}
			catch (Exception ex) {
				throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
			}
		}

		private AspectJAnnotationType determineAnnotationType(Annotation annotation) {
			AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
			if (type != null) {
				return type;
			}
			throw new IllegalStateException("Unknown annotation type: " + annotation);
		}

		private String resolvePointcutExpression(Annotation annotation) {
			for (String attributeName : EXPRESSION_ATTRIBUTES) {
				Object val = AnnotationUtils.getValue(annotation, attributeName);
				if (val instanceof String str && !str.isEmpty()) {
					return str;
				}
			}

View on GitHub (pinned to 69bf83ad71)