{"record":{"id":"f4850e064f694a2d","repo":"spring-projects/spring-framework","slug":"annotation-is-not-a-valid-aspectj-annotation","errorCode":null,"errorMessage":"{annotation} is not a valid AspectJ annotation","messagePattern":"(.+?) is not a valid AspectJ annotation","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java","lineNumber":189,"sourceCode":"\n\t\tprivate final Annotation annotation;\n\n\t\tprivate final AspectJAnnotationType annotationType;\n\n\t\tprivate final String pointcutExpression;\n\n\t\tprivate final String argumentNames;\n\n\t\tpublic AspectJAnnotation(Annotation annotation) {\n\t\t\tthis.annotation = annotation;\n\t\t\tthis.annotationType = determineAnnotationType(annotation);\n\t\t\ttry {\n\t\t\t\tthis.pointcutExpression = resolvePointcutExpression(annotation);\n\t\t\t\tObject argNames = AnnotationUtils.getValue(annotation, \"argNames\");\n\t\t\t\tthis.argumentNames = (argNames instanceof String names ? names : \"\");\n\t\t\t}\n\t\t\tcatch (Exception ex) {\n\t\t\t\tthrow new IllegalArgumentException(annotation + \" is not a valid AspectJ annotation\", ex);\n\t\t\t}\n\t\t}\n\n\t\tprivate AspectJAnnotationType determineAnnotationType(Annotation annotation) {\n\t\t\tAspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());\n\t\t\tif (type != null) {\n\t\t\t\treturn type;\n\t\t\t}\n\t\t\tthrow new IllegalStateException(\"Unknown annotation type: \" + annotation);\n\t\t}\n\n\t\tprivate String resolvePointcutExpression(Annotation annotation) {\n\t\t\tfor (String attributeName : EXPRESSION_ATTRIBUTES) {\n\t\t\t\tObject val = AnnotationUtils.getValue(annotation, attributeName);\n\t\t\t\tif (val instanceof String str && !str.isEmpty()) {\n\t\t\t\t\treturn str;\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java#L171-L207","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the chained cause exception (getCause()) to find the real reflective failure.","Ensure the advice annotation is the standard AspectJ annotation and not a custom meta-annotation that interferes with the 'pointcut'/'value' attribute.","Recompile the aspect class to rule out a stale/corrupt class file.","Verify the annotation is not being synthesized by a library that breaks AnnotationUtils.getValue semantics."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import org.springframework.core.annotation.AnnotationUtils;\n\npublic static boolean hasResolvablePointcut(java.lang.annotation.Annotation ann) {\n    for (String attr : new String[]{\"pointcut\", \"value\"}) {\n        Object v = AnnotationUtils.getValue(ann, attr);\n        if (v instanceof String s && !s.isEmpty()) return true;\n    }\n    return false;\n}\n\n// validate advice annotations before registering the aspect:\nfor (Method m : aspectClass.getDeclaredMethods()) {\n    for (var a : m.getAnnotations()) {\n        if (isAspectJAdvice(a) && !hasResolvablePointcut(a)) {\n            throw new IllegalStateException(\"Advice \" + m + \" has an unresolvable pointcut\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    List<Advisor> advisors = advisorFactory.getAdvisors(factory);\n} catch (IllegalArgumentException ex) {\n    if (ex.getCause() != null && ex.getMessage().contains(\"not a valid AspectJ annotation\")) {\n        // log the offending annotation and cause, skip the aspect\n    } else throw ex;\n}","preventionTips":["Avoid custom meta-annotations that mask the standard 'value'/'pointcut' attributes of advice annotations.","Keep aspects' bytecode clean; recompile after editing advice annotations.","In tests, instantiate the aspect and assert getAdvisors(factory) does not throw for each advice method."],"tags":["spring-aop","aspectj","annotations","reflection"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}